/** * Run the default json controller * * @param $parameters Parameters * @param $form array * @param $files array * @param $class_name string * @return string */ public function run(Parameters $parameters, $form, $files, $class_name) { $parameters = $parameters->getObjects(); // read all objects corresponding to class name if (!$parameters) { return json_encode(Dao::readAll(Names::setToClass($class_name, false), [Dao::sort()])); } // read object $first_parameter = reset($parameters); if (is_object($first_parameter)) { return json_encode($first_parameter); } // search objects for autocomplete combo pull-down list if (isset($parameters['term'])) { $element_class_name = Names::setToClass($class_name, false); $search = null; if (!empty($parameters['term'])) { $search = (new Search_Array_Builder())->buildMultiple(new Reflection_Class($element_class_name), $parameters['term'], '', '%'); } if (isset($parameters['filters']) && $parameters['filters']) { if (!(is_object($search) && $search->isAnd())) { $search = Dao\Func::andOp($search ? [$search] : []); } foreach ($parameters['filters'] as $filter_name => $filter_value) { $search->arguments[$filter_name] = $filter_value[0] == '!' ? Dao\Func::notEqual(substr($filter_value, 1)) : $filter_value; } if (count($search->arguments) == 1) { reset($search->arguments); $search = [key($search->arguments) => current($search->arguments)]; } } $objects = []; // first object only if (isset($parameters['first']) && $parameters['first']) { $objects = Dao::search($search, $element_class_name, [Dao::sort(), Dao::limit(1)]); $source_object = $objects ? reset($objects) : Builder::create($element_class_name); return json_encode(new Autocomplete_Entry(Dao::getObjectIdentifier($source_object), strval($source_object))); } else { $search_options = [Dao::sort()]; if (isset($parameters['limit'])) { $search_options[] = Dao::limit($parameters['limit']); } foreach (Dao::search($search, $element_class_name, $search_options) as $source_object) { $objects[] = new Autocomplete_Entry(Dao::getObjectIdentifier($source_object), strval($source_object)); } return json_encode($objects); } } elseif (isset($parameters['id'])) { $element_class_name = Names::setToClass($class_name); $source_object = Dao::read($parameters['id'], $element_class_name); return json_encode(new Autocomplete_Entry(Dao::getObjectIdentifier($source_object), strval($source_object))); } return ''; }
/** * Get the object of class $class_name from session * * @param $class_name string * @param $create_default boolean Create a default object for the class name if does not exist * @return object|null */ public function get($class_name, $create_default = false) { if (isset($this->current[$class_name])) { $current = $this->current[$class_name]; if (is_array($current)) { $current = $current[1]; $this->current[$class_name] = $current = is_numeric($current) ? Dao::read($current, $class_name) : unserialize($current); } return $current; } elseif ($create_default) { return $this->current[$class_name] = Builder::create($class_name); } else { return null; } }
/** * @param $parameters Parameters * @param $form array * @param $files array * @param $class_name string * @return mixed */ public function run(Parameters $parameters, $form, $files, $class_name) { $replaced = $parameters->getMainObject(); $objects = $parameters->getObjects(); if ($id_replace_with = $parameters->getRawParameter('id_replace_with')) { $objects['replace_with'] = $replacement = Dao::read($id_replace_with, $class_name); Dao::begin(); if ((new Delete_And_Replace())->deleteAndReplace($replaced, $replacement)) { Dao::commit(); $objects['done'] = true; } else { Dao::rollback(); $objects['error'] = true; } } return View::run($objects, $form, $files, $class_name, 'deleteAndReplace'); }
/** * This will be called for this controller, always. * * @param $parameters Parameters * @param $form array * @param $files array * @return mixed */ public function run(Parameters $parameters, $form, $files) { $environment = Session::current()->get(Environment::class, true); $objects = $parameters->getObjects(); $set_value = isset($objects['']) ? $objects[''] : (isset($objects[1]) ? $objects[1] : null); $name = $objects[0]; $this->property = (new Reflection_Class($environment))->getProperty($name); if ($set_value) { $type = $this->property->getType(); $environment->{$name} = $type->isClass() ? Dao::read($set_value, $type->asString()) : $set_value; $parameters->set('selected', true); return (new Output_Controller())->run($parameters, $form, $files); } else { $objects['controller'] = $this; $objects['name'] = $name; $objects = array_merge([get_class($environment) => $environment], $objects); return View::run($objects, $form, $files, get_class($environment), Feature::F_SELECT); } }
/** * Write an object into data source * * If object was originally read from data source, corresponding data will be overwritten * If object was not originally read from data source nor linked to it using replace(), a new * record will be written into data source using this object's data. * If object is null (all properties null or unset), the object will be removed from data source * * TODO LOWEST factorize this to become SOLID * * @param $object object object to write into data source * @param $options Option[] some options for advanced write * @return object the written object if written, or null if the object could not be written */ public function write($object, $options = []) { if ($this->beforeWrite($object, $options)) { if (Null_Object::isNull($object)) { $this->disconnect($object); } $class = new Link_Class(get_class($object)); $id_property = 'id'; foreach ($options as $option) { if ($option instanceof Only) { $only = isset($only) ? array_merge($only, $option->properties) : $option->properties; } } do { /** @var $link Class_\Link_Annotation */ $link = $class->getAnnotation('link'); if ($link->value) { $link_property = $link->getLinkClass()->getLinkProperty(); $link_object = $link_property->getValue($object); if (!$link_object) { $id_link_property = 'id_' . $link_property->name; $object->{$id_link_property} = $this->write($link_object, $options); } } $table_columns_names = array_keys($this->getStoredProperties($class)); $write_collections = []; $write_maps = []; $write = []; $aop_getter_ignore = Getter::$ignore; Getter::$ignore = true; $exclude_properties = $link->value ? array_keys((new Reflection_Class($link->value))->getProperties([T_EXTENDS, T_USE])) : []; /** @var $properties Reflection_Property[] */ $properties = $class->accessProperties(); $properties = Replaces_Annotations::removeReplacedProperties($properties); foreach ($properties as $property) { if (!isset($only) || in_array($property->name, $only)) { if (!$property->isStatic() && !in_array($property->name, $exclude_properties)) { $value = isset($object->{$property}) ? $property->getValue($object) : null; $property_is_null = $property->getAnnotation('null')->value; if (is_null($value) && !$property_is_null) { $value = ''; } if (in_array($property->name, $table_columns_names)) { $element_type = $property->getType()->getElementType(); // write basic if ($element_type->isBasic()) { $write[$property->getAnnotation('storage')->value] = is_array($value) ? json_encode($value) : $value; } elseif ($property->getAnnotation('store')->value == 'string') { $write[$property->getAnnotation('storage')->value] = is_array($value) ? serialize($value) : strval($value); } else { $column_name = 'id_' . $property->name; if (is_object($value)) { $value_class = new Link_Class(get_class($value)); $id_value = $value_class->getLinkedClassName() && !$element_type->asReflectionClass()->getAnnotation('link')->value ? 'id_' . $value_class->getCompositeProperty()->name : 'id'; $object->{$column_name} = $this->getObjectIdentifier($value, $id_value); if (empty($object->{$column_name})) { $object->{$column_name} = $this->getObjectIdentifier($this->write($value), $id_value); } } $write['id_' . $property->getAnnotation('storage')->value] = $property_is_null && !isset($object->{$column_name}) ? null : intval($object->{$column_name}); } } elseif (is_array($value) && $property->getAnnotation('link')->value == Link_Annotation::COLLECTION) { $write_collections[] = [$property, $value]; } elseif (is_array($value) && $property->getAnnotation('link')->value == Link_Annotation::MAP) { foreach ($value as $key => $val) { if (!is_object($val)) { $val = Dao::read($val, $property->getType()->getElementTypeAsString()); if (isset($val)) { $value[$key] = $val; } else { unset($value[$key]); } } } $write_maps[] = [$property, $value]; } } } } Getter::$ignore = $aop_getter_ignore; if ($write) { // link class : id is the couple of composite properties values if ($link->value) { $search = []; foreach ($link->getLinkProperties() as $property) { $property_name = $property->getName(); $column_name = $property->getType()->isClass() ? 'id_' : ''; $column_name .= $properties[$property_name]->getAnnotation('storage')->value; if (isset($write[$column_name])) { $search[$property_name] = $write[$column_name]; } elseif (isset($write[$property_name])) { $search[$property_name] = $write[$column_name]; } else { trigger_error("Can't search {$property_name}", E_USER_ERROR); } } if ($this->search($search, $class->name)) { $id = []; foreach ($search as $property_name => $value) { $column_name = $properties[$property_name]->getAnnotation('storage')->value; if (isset($write['id_' . $column_name])) { $column_name = 'id_' . $column_name; } $id[$column_name] = $value; unset($write[$column_name]); } } else { $id = null; } } else { $id = $this->getObjectIdentifier($object, $id_property); } if ($write) { $this->setContext($class->name); if (empty($id)) { $this->disconnect($object); $id = $this->query(Sql\Builder::buildInsert($class->name, $write)); if (!empty($id)) { $this->setObjectIdentifier($object, $id); } } else { $this->query(Sql\Builder::buildUpdate($class->name, $write, $id)); } } } foreach ($write_collections as $write) { list($property, $value) = $write; $this->writeCollection($object, $property, $value); } foreach ($write_maps as $write) { list($property, $value) = $write; $this->writeMap($object, $property, $value); } // if link class : write linked object too $id_property = $link->value ? 'id_' . $class->getCompositeProperty()->name : null; $class = $link->value ? new Link_Class($link->value) : null; } while ($class && !Null_Object::isNull($object, $class->name)); /** @var $after_writes Method_Annotation[] */ $after_writes = (new Reflection_Class(get_class($object)))->getAnnotations('after_write'); foreach ($after_writes as $after_write) { if ($after_write->call($object, [$this, $options]) === false) { break; } } return $object; } return null; }
/** * @param $list_settings Data_List_Settings * @return Reflection_Property_Value[] key is the property path */ public function getSearchValues(Data_List_Settings $list_settings) { $search = array_combine($list_settings->properties_path, $list_settings->properties_path); foreach ($list_settings->search as $property_path => $search_value) { if (isset($search[$property_path])) { $property = new Reflection_Property_Value($list_settings->class_name, $property_path, $search_value, true); if ($property->getType()->isClass()) { $property->value(Dao::read($search_value, $property->getType()->asString())); } else { $property->value($search_value); } $search[$property_path] = $property; } } return $search; }
/** * Initializes the object if not already set * - if a data link identifier is set, read the object from the data link and remove it from * $array * - if the object is a link class and the link class identifier properties values are set, * read the object from the data link * * @param $array array the source array * @param $object object the object to complete (if set) or to build (if null) * This object is always set at the end of execution of initObject() * @return array if read from a link object, this is the search properties that identify it */ private function initObject(&$array, &$object) { if (!isset($object)) { if (isset($array['id']) && $array['id']) { $object = Dao::read($array['id'], $this->class->name); } else { foreach ($this->class->getAnnotations('before_build_array') as $before) { call_user_func_array([$this->class->name, $before->value], [&$array]); } $link_search = $this->initLinkObject($array, $object); if (!isset($object)) { $object = $this->class->newInstance(); } } if (isset($array['id'])) { unset($array['id']); } } return isset($link_search) ? $link_search : null; }
/** * 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; }