Add subselect queries to count the relations.

@param  mixed  $relations
@return $this
542603
public function withCount($relations)
    {
        if (empty($relations)) {
            return $this;
        }
        if (is_null($this->query->columns)) {
            $this->query->select([$this->query->from.'.*']);
        }
        $relations = is_array($relations) ? $relations : func_get_args();
        foreach ($this->parseWithRelations($relations) as $name => $constraints) {
            // First we will determine if the name has been aliased using an "as" clause on the name
            // and if it has we will extract the actual relationship name and the desired name of
            // the resulting column. This allows multiple counts on the same relationship name.
            $segments = explode(' ', $name);
            unset($alias);
            if (count($segments) == 3 && mb_strtolower($segments[1]) == 'as') {
                list($name, $alias) = [$segments[0], $segments[2]];
            }
            $relation = $this->getRelationWithoutConstraints($name);
            // Here we will get the relationship count query and prepare to add it to the main query
            // as a sub-select. First, we'll get the "has" query and use that to get the relation
            // count query. We will normalize the relation name then append _count as the name.
            $query = $relation->getRelationExistenceCountQuery(
                $relation->getRelated()->newQuery(), $this
            );
            $query->callScope($constraints);
            $query->mergeConstraintsFrom($relation->getQuery());
            // Finally we will add the proper result column alias to the query and run the subselect
            // statement against the query builder. Then we will return the builder instance back
            // to the developer for further constraint chaining that needs to take place on it.
            $column = str_snake(isset($alias) ? $alias : $name).'_count';
            $this->selectSub($query->toBase(), $column);
        }
        return $this;
    }
896236
public function include($relations):SuccessResponseBuilder
    {
        if (is_string($relations)) {
            $relations = explode(',', $relations);
        }

        $this->relations = array_merge($this->relations, (array) $relations);

        return $this;
    }
241062
public function whereRelations(array $relations)
    {
        $instance = $this->whereStrategyInstance();

        $instance->whereStrategy()->whereRelations($relations);

        return $instance;
    }
1331706
protected function relationsToQueries()
    {
        foreach ($this->filters['strata_relations'] as $queryType => $queryDetails) {
            // At this point, there should only be exclusive AND or OR query groups
            $metaQueries = null;
            $relationTypes = array_keys($queryDetails);
            foreach ($relationTypes as $relationType) {
                if ($this->hasRelationQuery($queryType, $relationType)) {
                    $metaQueries = $this->getRelationQuery($queryType, $relationType);
                    $this->setQueryRelation($queryType, $relationType);
                    $this->resetQueryRelation($queryType, $relationType);
                }
            }

            if (!is_null($metaQueries)) {
                foreach ($metaQueries as $query) {
                    $this->addRelationQuery($queryType, $query);
                }
            }
        }

        return $this;
    }
707998
public function addRelationSelectColumns($relation)
    {
        $join = $this->joins[$relation];
        $join->getTableMap()->addSelectColumns($this, $join->getRelationAlias());

        return $this;
    }
479021
public function orRelations(array $relations)
    {
        foreach ($relations as $column1 => $column2) {
            $this->orRelation($column1, $column2);
        }

        return $this;
    }
800304
protected function hasOneOrManyDeepFromRelations(array $relations)
    {
        if (is_array($relations[0])) {
            $relations = $relations[0];
        }

        $related = null;
        $through = [];
        $foreignKeys = [];
        $localKeys = [];

        foreach ($relations as $i => $relation) {
            $method = $this->hasOneOrManyDeepRelationMethod($relation);

            [$through, $foreignKeys, $localKeys] = $this->$method($relation, $through, $foreignKeys, $localKeys);

            if ($i === count($relations) - 1) {
                $related = get_class($relation->getRelated());
            } else {
                $through[] = get_class($relation->getRelated());
            }
        }

        return [$related, $through, $foreignKeys, $localKeys];
    }
1101202
public function load($relations)
    {
        if (count($this->items) > 0) {
            if (is_string($relations)) {
                $relations = func_get_args();
            }

            $query = $this->first()->newQuery()->with($relations);

            $this->items = $query->eagerLoadRelations($this->items);
        }

        return $this;
    }
311434
protected function getRelationsArray(array $relations): array
    {
        $relationsArray = [];
        foreach ($relations as $relation) {
            $key = $relation->getName();

            $relationsArray[$key] = (new self($relation->getJory(), $this->minified))->get();
        }

        return $relationsArray;
    }
708266
public function countWhereHas($relation, array $where = [], array $whereHas = [])
    {
        $query = $this->make();

        $query = $this->applyWhere($query, $where);

        $query = $query->whereHas($relation, function ($q) use ($whereHas) {
            $this->applyWhere($q, $whereHas);
        });

        return $query->count();
    }
325518
public function createWith(array $attributes, array $relations) {
        // Collect the model attributes and label in the form of ['label' => $label, 'attributes' => $attributes]
        // as expected by the Query Builder.
        $attributes = $this->prepareForCreation($this->model, $attributes);
        $model = ['label' => $this->model->getTable(), 'attributes' => $attributes];

        /**
         * Collect the related models in the following for as expected by the Query Builder:
         *
         *  [
         *       'label' => ['Permission'],
         *       'relation' => [
         *           'name' => 'photos',
         *           'type' => 'PHOTO',
         *           'direction' => 'out',
         *       ],
         *       'values' => [
         *           // A mix of models and attributes, doesn't matter really..
         *           ['url' => '', 'caption' => ''],
         *           ['url' => '', 'caption' => '']
         *       ]
         *  ]
         */
        $related = [];
        foreach ($relations as $relation => $values) {
            $name = $relation;
            // Get the relation by calling the model's relationship function.
            if (!method_exists($this->model, $relation))
                throw new QueryException("The relation method $relation() does not exist on " . get_class($this->model));

            $relationship = $this->model->$relation();
            // Bring the model from the relationship.
            $relatedModel = $relationship->getRelated();

            // We will first check to see what the dev have passed as values
            // so that we make sure that we have an array moving forward
            // In the case of a model Id or an associative array or a Model instance it means that
            // this is probably a One-To-One relationship or the dev decided not to add
            // multiple records as relations so we'll wrap it up in an array.
            if (!is_array($values) || Helpers::isAssocArray($values) || $values instanceof Model)
                $values = [$values];

            $label = $relationship->getRelated()->getTable();
            $direction = $relationship->getEdgeDirection();
            $type = $relationship->getRelationType();

            // Hold the models that we need to attach
            $attach = [];
            // Hold the models that we need to create
            $create = [];
            // Separate the models that needs to be attached from the ones that needs
            // to be created.
            foreach ($values as $value) {
                // If this is a Model then the $exists property will indicate what we need
                // so we'll add its id to be attached.
                if ($value instanceof Model and $value->exists === true) {
                    $attach[] = $value->getKey();
                }
                // Next we will check whether we got a Collection in so that we deal with it
                // accordingly, which guarantees sending an Eloquent result straight in would work.
                elseif ($value instanceof Collection) {
                    $attach = array_merge($attach, $value->lists('id'));
                }
                // Or in the case where the attributes are neither an array nor a model instance
                // then this is assumed to be the model Id that the dev means to attach and since
                // Orientdb node Ids are always an int then we take that as a value.
                elseif (!is_array($value) && !$value instanceof Model) {
                    $attach[] = intval($value);
                }
                // In this case the record is considered to be new to the market so let's create it.
                else
                    $create[] = $this->prepareForCreation($relatedModel, $value);
            }

            $relation = compact('name', 'type', 'direction');
            $related[] = compact('relation', 'label', 'create', 'attach');
        }

        $result = $this->query->createWith($model, $related);

        $models = $this->resultsToModels($this->model->getConnectionName(), $result);
        return (!empty($models)) ? reset($models) : null;
    }
252522
protected function createRelatedEntities($relations)
    {
        $entitiesToCreate = $this->aggregate->getNonExistingRelated($relations);

        foreach ($entitiesToCreate as $aggregate) {
            $this->createStoreCommand($aggregate)->execute();
        }
    }
160794
public function initRelation(array $models, $relation)
    {
        foreach ($models as $model) {
            $model->setRelation($relation, $this->getDefaultFor($model));
        }

        return $models;
    }
611172
public function setRelations($relations)
    {
        $this->setAvailableIncludes(array_unique(array_merge($this->availableIncludes, (array) $relations)));

        return $this;
    }
537949
protected function getHasRelationQuery($relation)
	{
		$me = $this;

		return Relation::noConstraints(function() use ($me, $relation)
		{
			return $me->getModel()->$relation();
		});
	}
293667
protected function relationsNestedUnder($relation)
    {
        $nested = [];

        // We are basically looking for any relationships that are nested deeper than
        // the given top-level relationship. We will just check for any relations
        // that start with the given top relations and adds them to our arrays.
        foreach ($this->eagerLoad as $name => $constraints) {
            if ($this->isNestedUnder($relation, $name)) {
                $nested[substr($name, strlen($relation.'.'))] = $constraints;
            }
        }

        return $nested;
    }
185132
public function addQueries($queries) {
        if(is_array($queries)) {
            foreach($queries as $query) {
                $this->addQuery($query);
            }

            new Logger('Queries added to the queue.', Logger::DEBUG, __CLASS__, __LINE__);
            return $this;
        }

        new Logger('Failed to add to the queue.', Logger::ERROR, __CLASS__, __LINE__);
        return $this;
    }