Beispiel #1
0
 public static function getChainByDefinition(Base $init_entity, $definition)
 {
     $chain = new QueryChain();
     $chain->addElement(new QueryChainElement($init_entity));
     $def_elements = explode('.', $definition);
     $def_elements_size = count($def_elements);
     $prev_entity = $init_entity;
     $i = 0;
     foreach ($def_elements as &$def_element) {
         $is_last_elem = ++$i == $def_elements_size;
         $not_found = false;
         // all elements should be a Reference field or Entity
         // normal (scalar) field can only be the last element
         if ($prev_entity->hasField($def_element)) {
             // field has been found at current entity
             $field = $prev_entity->getField($def_element);
             if ($field instanceof ReferenceField) {
                 $prev_entity = $field->getRefEntity();
             } elseif ($field instanceof ExpressionField) {
                 // expr can be in the middle too
             } elseif (!$is_last_elem) {
                 throw new SystemException(sprintf('Normal fields can be only the last in chain, `%s` %s is not the last.', $field->getName(), get_class($field)));
             }
             if ($is_last_elem && $field instanceof ExpressionField) {
                 // we should have own copy of build_from_chains to set join aliases there
                 $field = clone $field;
             }
             $chain->addElement(new QueryChainElement($field));
         } elseif ($prev_entity->hasUField($def_element) && false) {
             /** @deprecated */
             // extend chain with utm/uts entity
             $ufield = $prev_entity->getUField($def_element);
             if ($ufield->isMultiple()) {
                 // add utm entity  user.utm:source_object (1:N)
                 $utm_entity = Base::getInstance($prev_entity->getNamespace() . 'Utm' . $prev_entity->getName());
                 $chain->addElement(new QueryChainElement(array($utm_entity, $utm_entity->getField('SOURCE_OBJECT')), array('ufield' => $ufield)));
                 if ($ufield->getTypeId() == 'iblock_section' && substr($ufield->getName(), -3) == '_BY' && $prev_entity->hasUField(substr($ufield->getName(), 0, -3))) {
                     // connect next entity
                     $utm_fname = $ufield->getName();
                     $prev_entity = Base::getInstance('Bitrix\\Iblock\\Section');
                 } else {
                     $utm_fname = $ufield->getValueFieldName();
                 }
                 $chain->addElement(new QueryChainElement($utm_entity->getField($utm_fname), array('ufield' => $ufield)));
             } else {
                 // uts table - single value
                 // add uts entity user.uts (1:1)
                 $uts_entity = Base::getInstance($prev_entity->getNamespace() . 'Uts' . $prev_entity->getName());
                 $chain->addElement(new QueryChainElement($prev_entity->getField('UTS_OBJECT')));
                 // add `value` field
                 $chain->addElement(new QueryChainElement($uts_entity->getField($def_element)));
             }
         } elseif (Base::isExists($def_element) && Base::getInstance($def_element)->getReferencesCountTo($prev_entity->getName()) == 1) {
             // def_element is another entity with only 1 reference to current entity
             // need to identify Reference field
             $ref_entity = Base::getInstance($def_element);
             $field = end($ref_entity->getReferencesTo($prev_entity->getName()));
             $prev_entity = $ref_entity;
             $chain->addElement(new QueryChainElement(array($ref_entity, $field)));
         } elseif (($pos_wh = strpos($def_element, ':')) > 0) {
             $ref_entity_name = substr($def_element, 0, $pos_wh);
             if (strpos($ref_entity_name, '\\') === false) {
                 // if reference has no namespace, then it'is in the namespace of previous entity
                 $ref_entity_name = $prev_entity->getNamespace() . $ref_entity_name;
             }
             if (Base::isExists($ref_entity_name) && Base::getInstance($ref_entity_name)->hasField($ref_field_name = substr($def_element, $pos_wh + 1)) && Base::getInstance($ref_entity_name)->getField($ref_field_name) instanceof ReferenceField) {
                 /** @var ReferenceField $reference */
                 $reference = Base::getInstance($ref_entity_name)->getField($ref_field_name);
                 if ($reference->getRefEntity()->getFullName() == $prev_entity->getFullName()) {
                     // chain element is another entity with >1 references to current entity
                     // def like NewsArticle:AUTHOR, NewsArticle:LAST_COMMENTER
                     // NewsArticle - entity, AUTHOR and LAST_COMMENTER - Reference fields
                     $chain->addElement(new QueryChainElement(array(Base::getInstance($ref_entity_name), Base::getInstance($ref_entity_name)->getField($ref_field_name))));
                     $prev_entity = Base::getInstance($ref_entity_name);
                 } else {
                     $not_found = true;
                 }
             } else {
                 $not_found = true;
             }
         } elseif ($def_element == '*' && $is_last_elem) {
             continue;
         } else {
             // unknown chain
             $not_found = true;
         }
         if ($not_found) {
             throw new SystemException(sprintf('Unknown field definition `%s` (%s) for %s Entity.', $def_element, $definition, $prev_entity->getName()), 100);
         }
     }
     return $chain;
 }