public function testManyEagerLoadsAndConstraintsWithLoaderFromResultset()
 {
     $manufacturers = Loader::fromResultset(Manufacturer::find(), ['Robots.Bugs' => function (QueryBuilder $builder) {
         $builder->where('Bug.id > 10');
     }]);
     $robots = array();
     foreach ($manufacturers as $m) {
         $robots = array_merge($robots, $m->robots);
     }
     $this->assertEquals(array_sum(array_map(function ($o) {
         return count($o->bugs);
     }, $robots)), 134);
 }
 /**
  * <code>
  * <?php
  *
  * $manufacturer = Manufacturer::findFirstById(51);
  *
  * $manufacturer->load('Robots.Parts');	
  *
  * foreach ($manufacturer->robots as $robot) {
  *    foreach ($robot->parts as $part) { ... }
  * }
  * </code>
  *
  * @param mixed ...$arguments
  * @return self
  */
 public function load(...$arguments)
 {
     return Loader::fromModel($this, ...$arguments);
 }
 /**
  * Executes each db query needed
  *
  * Note: The {$alias} property is set two times because Phalcon Model ignores
  * empty arrays when overloading property set.
  *
  * Also {@see https://github.com/stibiumz/phalcon.eager-loading/issues/1}
  *
  * @return $this
  */
 public function load()
 {
     if (empty($this->parent->getSubject())) {
         return $this;
     }
     $relation = $this->relation;
     $alias = strtolower($relation->getOptions()['alias']);
     $relField = $relation->getFields();
     $relReferencedModel = $relation->getReferencedModel();
     $relReferencedField = $relation->getReferencedFields();
     $relIrModel = $relation->getIntermediateModel();
     $relIrField = $relation->getIntermediateFields();
     $relIrReferencedField = $relation->getIntermediateReferencedFields();
     // PHQL has problems with this slash
     if ($relReferencedModel[0] === '\\') {
         $relReferencedModel = ltrim($relReferencedModel, '\\');
     }
     $bindValues = [];
     foreach ($this->parent->getSubject() as $record) {
         $bindValues[$record->readAttribute($relField)] = TRUE;
     }
     $bindValues = array_filter(array_keys($bindValues));
     $subjectSize = count($this->parent->getSubject());
     $isManyToManyForMany = FALSE;
     $builder = new QueryBuilder();
     $builder->from($relReferencedModel);
     if ($isThrough = $relation->isThrough()) {
         if ($subjectSize === 1) {
             // The query is for a single model
             $builder->innerJoin($relIrModel, sprintf('[%s].[%s] = [%s].[%s]', $relIrModel, $relIrReferencedField, $relReferencedModel, $relReferencedField))->inWhere("[{$relIrModel}].[{$relIrField}]", $bindValues);
         } else {
             // The query is for many models, so it's needed to execute an
             // extra query
             $isManyToManyForMany = TRUE;
             if (isset($bindValues)) {
                 $relIrValues = (new QueryBuilder())->from($relIrModel)->inWhere("[{$relIrModel}].[{$relIrField}]", $bindValues)->getQuery()->execute()->setHydrateMode(Resultset::HYDRATE_ARRAYS);
             }
             $bindValues = $modelReferencedModelValues = [];
             if (isset($relIrValues)) {
                 foreach ($relIrValues as $row) {
                     $bindValues[$row[$relIrReferencedField]] = TRUE;
                     $modelReferencedModelValues[$row[$relIrField]][$row[$relIrReferencedField]] = TRUE;
                 }
             }
             unset($relIrValues, $row);
             $builder->inWhere("[{$relReferencedField}]", array_keys($bindValues));
         }
     } else {
         $builder->inWhere("[{$relReferencedField}]", $bindValues);
     }
     if ($this->constraints) {
         call_user_func($this->constraints, $builder);
     }
     $records = [];
     if ($isManyToManyForMany) {
         if ($bindValues) {
             foreach ($builder->getQuery()->execute() as $record) {
                 $records[$record->readAttribute($relReferencedField)] = $record;
             }
         }
         foreach ($this->parent->getSubject() as $record) {
             $referencedFieldValue = $record->readAttribute($relField);
             if (isset($modelReferencedModelValues[$referencedFieldValue])) {
                 $referencedModels = [];
                 foreach ($modelReferencedModelValues[$referencedFieldValue] as $idx => $_) {
                     $referencedModels[] = $records[$idx];
                 }
                 $record->{$alias} = $referencedModels;
                 if (static::$isPhalcon2) {
                     $record->{$alias} = NULL;
                     $record->{$alias} = $referencedModels;
                 }
             } else {
                 $record->{$alias} = NULL;
                 $record->{$alias} = [];
             }
         }
         $records = array_values($records);
     } else {
         // We expect a single object or a set of it
         $isSingle = !$isThrough && ($relation->getType() === Relation::HAS_ONE || $relation->getType() === Relation::BELONGS_TO);
         if ($subjectSize === 1) {
             // Keep all records in memory
             if ($bindValues) {
                 foreach ($builder->getQuery()->execute() as $record) {
                     $records[] = $record;
                 }
             }
             if ($isSingle) {
                 $this->parent->getSubject()[0]->{$alias} = empty($records) ? NULL : $records[0];
             } else {
                 $record = $this->parent->getSubject()[0];
                 if (empty($records)) {
                     $record->{$alias} = NULL;
                     $record->{$alias} = [];
                 } else {
                     $record->{$alias} = $records;
                     if (static::$isPhalcon2) {
                         $record->{$alias} = NULL;
                         $record->{$alias} = $records;
                     }
                 }
             }
         } else {
             $indexedRecords = [];
             // Keep all records in memory
             if ($bindValues) {
                 foreach ($builder->getQuery()->execute() as $record) {
                     $records[] = $record;
                     if ($isSingle) {
                         $indexedRecords[$record->readAttribute($relReferencedField)] = $record;
                     } else {
                         $indexedRecords[$record->readAttribute($relReferencedField)][] = $record;
                     }
                 }
             }
             foreach ($this->parent->getSubject() as $record) {
                 $referencedFieldValue = $record->readAttribute($relField);
                 if (isset($indexedRecords[$referencedFieldValue])) {
                     $record->{$alias} = $indexedRecords[$referencedFieldValue];
                     if (static::$isPhalcon2 && is_array($indexedRecords[$referencedFieldValue])) {
                         $record->{$alias} = NULL;
                         $record->{$alias} = $indexedRecords[$referencedFieldValue];
                     }
                 } else {
                     $record->{$alias} = NULL;
                     if (!$isSingle) {
                         $record->{$alias} = [];
                     }
                 }
             }
         }
     }
     $this->subject = $records;
     return $this;
 }