/** * Extends the list of sources to compile * * When you modify a file, all these classes may have their matching mysql structure changed : * - the class itself * - all classes that extend the class or use the trait * * @param &$sources Reflection_Source[] * @return Reflection_Source[] added sources list */ public function moreSourcesToCompile(&$sources) { $added = []; // Builder is disabled during the listing as we want to get the original linked class name when // reading class annotation @link Builder::current()->enabled = false; /** @var $search Dependency */ $search = Search_Object::create(Dependency::class); $search->file_name = Func::notLike('cache/%'); $search->type = Func::orOp([Dependency::T_EXTENDS, Dependency::T_USE]); foreach ($sources as $source) { foreach ($source->getClasses() as $class) { while ($linked_class = $class->getAnnotation('link')->value) { $source = Reflection_Class::of($linked_class)->source; if (!isset($sources[$source->file_name])) { $sources[$source->file_name] = $source; $added[$source->file_name] = $source; } $class = $source->getClass($linked_class); } $search->dependency_name = $class->name; foreach (Dao::search($search, Dependency::class) as $dependency) { /** @var $dependency Dependency */ if (!isset($sources[$dependency->file_name])) { $source = new Reflection_Source($dependency->file_name); $sources[$dependency->file_name] = $source; $added[$dependency->file_name] = $source; } } } } Builder::current()->enabled = true; return $added; }
/** * Set identifier unique */ public function uniqueIdentifier() { if (isset($this->identifier)) { /** @var $search Identifier */ $search = Search_Object::create(Identifier::class); $search->name = $this->identifier->name; if ($find = Dao::searchOne($search)) { Dao::replace($this->identifier, $find, false); } else { Dao::disconnect($this->identifier); } } }
/** * Generic getter for a collection of objects * * @param $stored Component[] Actual value of the property (will be returned if not null) * @param $class_name string Class for each collection's object * @param $object object Parent object * @param $property string|Reflection_Property Parent property (or property name). Recommended * but can be omitted if foreign class is a Component * @return object[] */ public static function &getCollection(&$stored, $class_name, $object, $property = null) { if (!(self::$ignore || isset($stored))) { if (Dao::getObjectIdentifier($object)) { $search_element = Search_Object::create($class_name); $is_component = isA($search_element, Component::class); if (isset($property)) { if (!$property instanceof Reflection_Property) { $property = new Reflection_Property(get_class($object), $property); } $property_name = $property->getAnnotation('foreign')->value; $dao = ($dao = $property->getAnnotation('dao')->value) ? Dao::get($dao) : Dao::current(); } else { $dao = Dao::current(); $property_name = null; } if ($is_component) { /** @var $search_element Component */ $search_element->setComposite($object, $property_name); $link_properties_names = (new Link_Class($class_name))->getLinkPropertiesNames(); $options = $link_properties_names ? [Dao::sort(), Dao::key($link_properties_names)] : [Dao::sort()]; $stored = $dao->search($search_element, null, $options); } elseif (!empty($property_name)) { $property = new Reflection_Property(get_class($search_element), $property_name); $accessible = $property->isPublic(); if (!$accessible) { $property->setAccessible(true); } $property->setValue($search_element, $object); if (!$accessible) { $property->setAccessible(false); } $stored = $dao->search($search_element, null, [Dao::sort()]); } else { trigger_error('getCollection() must be called for a component foreign type' . ' or with a parent property name', E_USER_ERROR); } } if (!isset($stored)) { $stored = []; } } return $stored; }
/** * When a class is compiled, all classes that extends it must be compiled too * * @param &$sources Reflection_Source[] * @return Reflection_Source[] added sources list */ public function moreSourcesToCompile(&$sources) { $added = []; // we will search all extends dependencies /** @var $dependency Dependency */ $dependency_search = Search_Object::create(Dependency::class); $dependency_search->type = Dependency::T_EXTENDS; foreach ($sources as $source) { foreach ($source->getClasses() as $class) { if (!Builder::isBuilt($class->name)) { // add all classes that extend source classes $dependency_search->dependency_name = $class->name; foreach (Dao::search($dependency_search) as $dependency) { if (!isset($sources[$dependency->file_name]) && !Builder::isBuilt($dependency->class_name)) { $added[$dependency->file_name] = new Reflection_Source($dependency->file_name); } } } } } return $added; }
/** * Reverse translator : changes a translated text into an original text * * @param $translation string * @param $context string * @param $context_property_path string ie 'property_name.sub_property', accepts (and ignore) '*' * @return string */ public function reverse($translation, $context = '', $context_property_path = '') { if (empty($translation)) { return $translation; } $context_property = str_replace('*', '', $context_property_path); /** @var $search Translation */ $search = Search_Object::create(Translation::class); $search->language = $this->language; $search->translation = strtolower($translation); $search->context = $context_property_path ? (new Reflection_Property($context, $context_property))->final_class : $context; $texts = Dao::search($search); foreach ($texts as $text) { if ($text->translation === $translation) { break; } } while (isset($search->context) && $search->context && !isset($text)) { $i = strrpos($search->context, DOT); $search->context = $i ? substr($search->context, 0, $i) : ''; $texts = Dao::search($search); foreach ($texts as $text) { if ($text->translation === $translation) { break; } } } if (!isset($text) && strpos($translation, ', ')) { $text_parts = []; foreach (explode(', ', $translation) as $translation_part) { $text_parts[] = $this->reverse($translation_part, $context, $context_property_path); } $text = new Translation(join(', ', $text_parts), $this->language, $context, $translation); } $text = isset($text) ? $text->text : $translation; return empty($text) ? $text : (strIsCapitals($translation[0]) ? ucfirsta($text) : $text); }
/** * @param $sources Reflection_Source[] * @return Reflection_Source[] added sources list */ public function moreSourcesToCompile(&$sources) { $added = []; // search into dependencies : used classes /** @var $search Dependency */ $search = Search_Object::create(Dependency::class); $search->type = Dependency::T_USE; foreach ($sources as $source) { foreach ($source->getClasses() as $class) { if ($class->type === T_TRAIT) { $search->dependency_name = $class->name; foreach (Dao::search($search, Dependency::class) as $dependency) { while ($dependency && Builder::isBuilt($dependency->class_name)) { $search_built_parent = Search_Object::create(Dependency::class); $search_built_parent->class_name = $dependency->class_name; $search_built_parent->type = Dependency::T_EXTENDS; $dependency = Dao::searchOne($search_built_parent); if (!$dependency) { trigger_error('Not parent class for built class ' . $search_built_parent->class_name, E_USER_ERROR); } $search_built_parent->class_name = $dependency->dependency_name; $search_built_parent->type = Dependency::T_DECLARATION; $dependency = Dao::searchOne($search_built_parent); if (!$dependency) { trigger_error('Not declaration dependency for class ' . $search_built_parent->class_name, E_USER_ERROR); } } /** @var $dependency Dependency */ if (!isset($sources[$dependency->file_name])) { $source = new Reflection_Source($dependency->file_name); $sources[$dependency->file_name] = $source; $added[$dependency->file_name] = $source; } } } } } // search into dependencies : registered methods foreach ($sources as $source) { $search->file_name = $source->file_name; $search->dependency_name = Registerable::class; $search->type = Dependency::T_IMPLEMENTS; if (Dao::searchOne($search, Dependency::class)) { unset($search->dependency_name); $search->type = Dependency::T_CLASS; foreach (Dao::search($search, Dependency::class) as $dependency) { $source = Reflection_Source::of($dependency->dependency_name); if (!isset($sources[$source->file_name])) { $sources[$source->file_name] = $source; $added[$source->file_name] = $source; } } } } // classes that are already into $sources $already = []; foreach ($sources as $source) { foreach ($source->getClasses() as $class) { $already[$class->name] = true; } } // search into advices and add sources that have sources to compile as advice foreach ($this->weaver->getJoinpoints() as $class_name => $joinpoint) { if (!isset($already[$class_name])) { foreach ($joinpoint as $advices) { foreach ($advices as $advice) { if (is_array($advice = $advice[1])) { $advice_class = $advice[0]; if (is_object($advice_class)) { $advice_class = get_class($advice_class); } if (isset($already[$advice_class])) { $source = Reflection_Source::of($class_name); /* if ($source->file_name && !$source->isInternal() && !is_file($source->file_name)) { $applicant_source = Reflection_Source::of($advice_class); if ( !$source->searchFile($class_name, array_keys($applicant_source->getRequires())) ) { trigger_error( 'Reflection_Source file not found for class ' . $class_name, E_USER_ERROR ); } } */ if ($source->getClass($class_name)) { $sources[$source->file_name] = $source; $added[$source->file_name] = $source; $already[$class_name] = true; } else { trigger_error('No class ' . $class_name . ' into file ' . $source->file_name, E_USER_ERROR); } } } } } } } return $added; }
/** * Login to current environment using login and password * * Returns logged user if success * To set logger user as current for environment, you must call authenticate() * * @param $login string * @param $password string * @return User|null */ public static function login($login, $password) { $search = Search_Object::create(User::class); $search->login = $login; $password = (new Password($password, (new Reflection_Property(get_class($search), 'password'))->getAnnotation('password')->value))->encrypted(); foreach (Dao::search($search) as $user) { if ($user->password === $password) { return $user; } } return null; }
/** * @param $object object * @param $property Reflection_Property * @param $map object[] */ private function writeMap($object, Reflection_Property $property, $map) { // old map $class = new Link_Class(get_class($object)); $composite_property_name = $class->getAnnotation('link')->value ? $class->getCompositeProperty()->name : null; $old_object = Search_Object::create(Link_Class::linkedClassNameOf($object)); $this->setObjectIdentifier($old_object, $this->getObjectIdentifier($object, $composite_property_name)); $aop_getter_ignore = Getter::$ignore; Getter::$ignore = false; $old_map = $property->getValue($old_object); Getter::$ignore = $aop_getter_ignore; // map properties : write each of them $insert_builder = new Map_Insert($property); $id_set = []; foreach ($map as $element) { $id = $this->getObjectIdentifier($element) ?: $this->getObjectIdentifier($this->write($element)); if (!isset($old_map[$id])) { $query = $insert_builder->buildQuery($object, $element); $this->connection->query($query); } else { $id_set[$id] = true; } } // remove old unused elements $delete_builder = new Map_Delete($property); foreach ($old_map as $old_element) { $id = $this->getObjectIdentifier($old_element); if (!isset($id_set[$id])) { $query = $delete_builder->buildQuery($object, $old_element); $this->connection->query($query); } } }
public function testWhereSubSearchObjectQuery() { $client = Search_Object::create(Client::class); $client->number = 1; $builder = new Select(Order::class, ['date', 'number', 'lines'], ['lines.client' => $client, 'number' => 2]); $this->assume(__METHOD__, $builder->buildQuery(), 'SELECT t0.`date`, t0.`number`, t1.`id_client` AS `lines:client`, t1.`id_item` AS `lines:item`, t1.`number` AS `lines:number`, t1.`id_order` AS `lines:order`, t1.`quantity` AS `lines:quantity`, t1.id AS `lines:id`' . LF . 'FROM `orders` t0' . LF . 'INNER JOIN `orders_lines` t1 ON t1.id_order = t0.id' . LF . 'LEFT JOIN `clients` t2 ON t2.id = t1.id_client' . LF . 'WHERE t2.`number` = 1 AND t0.`number` = 2'); }
/** * Be sure that recipients are unique into data storage * - they can be common to several emails * - modification of recipients is not allowed */ private function uniqueRecipents() { /** @var $search Recipient */ $search = Search_Object::create(Recipient::class); $recipients = array_merge([$this->from, $this->reply_to, $this->return_path], $this->to, $this->copy_to, $this->blind_copy_to); $already = []; foreach ($recipients as $recipient) { if (isset($recipient)) { $search->email = $recipient->email; $search->name = $recipient->name; if (isset($already[strval($search)])) { Dao::replace($recipient, $already[strval($search)], false); } else { $already[strval($search)] = $recipient; if ($find = Dao::searchOne($recipient)) { Dao::replace($recipient, $find, false); } else { Dao::disconnect($recipient); } } } } }