Scalr\Api\DataType\ApiEntityAdapter::getCriteria PHP Method

getCriteria() public method

Adjusts search criteria according to RULE_TYPE_FILTERABLE rules and Request
public getCriteria ( array $criteria = null ) : array | null
$criteria array optional Default search criteria
return array | null Returns adjusted criteria
    public function getCriteria($criteria = null)
    {
        $rules = $this->getRules();
        if (!empty($rules[static::RULE_TYPE_FILTERABLE])) {
            if (!is_array($rules[static::RULE_TYPE_FILTERABLE]) && !$rules[static::RULE_TYPE_FILTERABLE] instanceof \ArrayAccess) {
                throw new \InvalidArgumentException(sprintf("[%s::RULE_TYPE_FILTERABLE] offset of the rules is expected to be an Array", get_class($this)));
            }
            /* @var $entity AbstractEntity */
            $entityClass = $this->getEntityClass();
            $entity = new $entityClass();
            $it = $entity->getIterator();
            //Search criteria
            $criteria = $criteria ?: [];
            $settingsRules = null;
            foreach ($rules[static::RULE_TYPE_FILTERABLE] as $property) {
                $key = null;
                //Gets value from the request
                $filterValue = $this->controller->params($property);
                if ($filterValue === null) {
                    continue;
                }
                //As the name of the property that goes into response may be different from the
                //real property name in the Entity object it should be mapped at first
                if (!empty($rules[static::RULE_TYPE_TO_DATA])) {
                    //if toData rule is null it means all properties are allowed
                    if (($key = array_search($property, $rules[static::RULE_TYPE_TO_DATA])) !== false) {
                        if (is_string($key)) {
                            //In this case the real name of the property is the key of the array
                            if ($key[0] === '_' && method_exists($this, $key)) {
                                //It is callable
                                $from = (object) [$property => $filterValue];
                                $addCriteria = $this->{$key}($from, null, self::ACT_GET_FILTER_CRITERIA);
                                if (!empty($addCriteria)) {
                                    if (isset($addCriteria[AbstractEntity::STMT_FROM])) {
                                        if (!isset($criteria[AbstractEntity::STMT_FROM])) {
                                            $criteria[AbstractEntity::STMT_FROM] = $entity->table();
                                        }
                                        $criteria[AbstractEntity::STMT_FROM] .= " " . $addCriteria[AbstractEntity::STMT_FROM];
                                    }
                                    if (isset($addCriteria[AbstractEntity::STMT_WHERE])) {
                                        if (!empty($criteria[AbstractEntity::STMT_WHERE])) {
                                            $criteria[AbstractEntity::STMT_WHERE] .= " AND (" . $addCriteria[AbstractEntity::STMT_WHERE] . ")";
                                        } else {
                                            $criteria[AbstractEntity::STMT_WHERE] = $addCriteria[AbstractEntity::STMT_WHERE];
                                        }
                                    }
                                    //Latter value should not overwrite the previous
                                    $criteria = array_merge($addCriteria, $criteria);
                                }
                                continue;
                            }
                            $property = $key;
                        }
                    }
                }
                if (empty($key) && !empty($rules[static::RULE_TYPE_SETTINGS]) && method_exists($entity, 'getSettingCriteria')) {
                    if (!isset($settingsRules)) {
                        $settingsRules = $this->getSettingsRules();
                    }
                    if (($key = array_search($property, $settingsRules)) !== false) {
                        if (is_object($filterValue) || is_array($filterValue)) {
                            throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_VALUE, "Filter value must be a string");
                        }
                        if (empty($criteria[AbstractEntity::STMT_FROM])) {
                            $criteria[AbstractEntity::STMT_FROM] = " {$entity->table()} ";
                        }
                        $criteria = $entity->getSettingCriteria($key, $filterValue, $criteria);
                        continue;
                    }
                }
                //Fetches the definition of the field from the Entity model
                $field = $it->getField($property);
                if (!$field instanceof Field) {
                    throw new \InvalidArgumentException(sprintf("Invalid value is in the [%s::RULE_TYPE_FILTERABLE] offset of the rules. " . "Property '%s' is not defined in the %s entity.", get_class($this), $property, get_class($entity)));
                }
                //Different column type values should be converted
                $criteria[] = [$field->name => static::convertInputValue($field->column->type, $filterValue, $property)];
            }
        }
        //We should make sure users do not send requests with unavailable filters.
        $notProcessed = array_diff(array_keys($this->controller->request->get()), array_keys($this->controller->getCommonQueryParams()), !empty($rules[static::RULE_TYPE_FILTERABLE]) ? $rules[static::RULE_TYPE_FILTERABLE] : array_values($rules[static::RULE_TYPE_TO_DATA]));
        if (!empty($notProcessed)) {
            //It means user sent request to filter on not filterable property.
            throw new ApiErrorException(400, ErrorMessage::ERR_INVALID_STRUCTURE, sprintf("Unsupported filter. Fields which are available for filtering: [%s]", join(', ', $rules[static::RULE_TYPE_FILTERABLE])));
        }
        return $criteria;
    }