protected function newQuery(array $options = array(), $modelClass = null)
    {
        $options = array_replace(array(
            'includes' => array(),
            'order_by' => array(),
            'where'    => array(),
            'has'      => array(), // relationships
        ), $options);

        if (!is_string($modelClass)) {
            $modelClass = $this->modelClass;
        }
        $query = call_user_func(array(new $modelClass(), 'newQuery'));

        /*
         * Includes
         */
        if (is_array($options['includes'])) {
            $includes = array_values($options['includes']);

            foreach ($includes as $include) {
                if (in_array($include, $this->includableRelationships)) {
                    $query->with($include);
                }
            }
        }

        /*
         * Where
         */
        if (is_array($options['where'])) {
            foreach ($options['where'] as $condition) {
                if (
                    is_array($condition)
                    && count($condition) == 3
                ) {
                    $query->where($condition[0], $condition[1], $condition[2]);
                }
            }
        }

        /*
         * Has
         */
        if (is_array($options['has'])) {
            foreach ($options['has'] as $relation => $conditions) {
                if (
                    is_string($relation)
                    && is_array($conditions)
                ) {
                    $query->whereHas($relation, function ($q) use ($conditions) {
                        $i = 0;
                        foreach ($conditions as $condition) {
                            if (
                                is_array($condition)
                                && count($condition) == 2
                            ) {
                                // TODO: our goal is to reduce the subcondition, e.g.:
                                // select * from `categories` where (select count(*) from `category_translations` where `category_translations`.`category_id` = `categories`.`id` and (`slug` = "men" or `slug` = "shoes")) >= 1
                                // current implementation is missing the "()" between the `slug` condition, like this:
                                // select * from `categories` where (select count(*) from `category_translations` where `category_translations`.`category_id` = `categories`.`id` and `slug` = "men" and `slug` = "shoes") >= 1
                                // obviously, not the same result
                                // if( $i == 0 )
                                // {
                                    $q->where($condition[0], $condition[1]);
                                // }
                                // else
                                // {
                                //     $q->orWhere($condition[0], $condition[1]);
                                // }

                                // ++$i;
                            }
                        }
                    });
                }
            }
        }

        /*
        * orders
        */
        if (is_string($options['order_by'])) {
            $options['order_by'] = json_decode($options['order_by'], true);
        }
        if (is_array($options['order_by'])) {
            foreach ($options['order_by'] as $field => $direction) {
                $direction = strtoupper($direction);

                // TODO implement orderableFields
                if (
                    is_string($field)
                    && in_array($direction, array('ASC', 'DESC'))
                    // && in_array($field, $this->orderableFields)
                ) {
                    $query->orderBy($field, $direction);
                }
            }
        }

        return $query;
    }