diff --git a/plugins/services_entity_abstract.inc b/plugins/services_entity_abstract.inc index 76b2367..1f9153b 100644 --- a/plugins/services_entity_abstract.inc +++ b/plugins/services_entity_abstract.inc @@ -246,6 +246,18 @@ abstract class ServicesResourceControllerAbstract implements ServicesResourceCon 'default value' => 'ASC', 'source' => array('param' => 'direction'), ); + + /** + * Additional search options, such as sort operators. + */ + $info['index']['args'][] = array( + 'name' => 'options', + 'optional' => TRUE, + 'type' => 'array', + 'description' => 'Additional query options.', + 'default value' => array(), + 'source' => array('param' => 'options'), + ); return $info; } diff --git a/plugins/services_entity_interface.inc b/plugins/services_entity_interface.inc index 676c4ec..8657015 100644 --- a/plugins/services_entity_interface.inc +++ b/plugins/services_entity_interface.inc @@ -94,14 +94,22 @@ interface ServicesResourceControllerInterface { * * @param string $entity_type * The type of the resource that should be deleted. - * @param array $filters - * field comparison operators to filter the results. + * @param string $fields + * The fields to be returned. + * @param array $parameters + * Property and field parameters comparison operators to filter the results. * @param int $page - * The page of resources to be returned - * @param int $limit + * The page of resources to be returned. + * @param int $pagesize * The number of items on that pages to be returned. + * @param string $sort + * What field or property to sort on. + * @param string $direction + * The sort direction + * @param array $options + * Any additioinal options for this search. */ - public function index($entity_type, $fields, $parameters, $page, $pagesize, $sort, $direction); + public function index($entity_type, $fields, $parameters, $page, $pagesize, $sort, $direction, $options); /** * Get the value of a single field. diff --git a/plugins/services_entity_resource.inc b/plugins/services_entity_resource.inc index 4f63271..5e0704f 100644 --- a/plugins/services_entity_resource.inc +++ b/plugins/services_entity_resource.inc @@ -109,7 +109,7 @@ class ServicesEntityResourceController extends ServicesResourceControllerAbstrac /** * Implements ServicesResourceControllerInterface::index(). */ - public function index($entity_type, $fields, $parameters, $page, $pagesize, $sort, $direction) { + public function index($entity_type, $fields, $parameters, $page, $pagesize, $sort, $direction, $options = array()) { // Make sure the pagesize is not too large. $max_pagesize = variable_get('services_entity_max_pagesize', 100); $pagesize = ($max_pagesize < $pagesize) ? $max_pagesize : $pagesize; @@ -122,7 +122,12 @@ class ServicesEntityResourceController extends ServicesResourceControllerAbstrac if (!empty($parameters)) { foreach ($parameters as $field => $value) { - $this->propertyQueryOperation($entity_type, $query, 'Condition', $field, $value); + $operator = ( + !empty($options['parameters_op'][$field]) ? + $this->filterOperator($options['parameters_op'][$field], $value) : + $this->defaultOperator($value) + ); + $this->propertyQueryOperation($entity_type, $query, 'Condition', $field, $value, $operator); } } if ($sort != '') { @@ -237,7 +242,7 @@ class ServicesEntityResourceController extends ServicesResourceControllerAbstrac * @param string|array $value * The value for the function. */ - protected function propertyQueryOperation($entity_type, EntityFieldQuery $query, $operation, $property, $value) { + protected function propertyQueryOperation($entity_type, EntityFieldQuery $query, $operation, $property, $value, $operator = '=') { // First pass: check the entity's table schema. // Get the database schema for the entity's table. $entity_info = entity_get_info($entity_type); @@ -246,7 +251,7 @@ class ServicesEntityResourceController extends ServicesResourceControllerAbstrac // If the property is defined in the schema, use the schema property. // The EFQ method is either 'propertyCondition' or 'OrderByCondition'. $operation = 'property' . $operation; - $query->$operation($property, $value); + $query->$operation($property, $value, $operator); return; } @@ -263,14 +268,14 @@ class ServicesEntityResourceController extends ServicesResourceControllerAbstrac // Specific column filters are given, so add a query condition for each // one of them. foreach ($value as $column => $val) { - $query->$operation($field_info, $column, $val); + $query->$operation($field_info, $column, $val, $operator); } } else { // Just pick the first field column for the operation. $columns = array_keys($field_info['columns']); $column = $columns[0]; - $query->$operation($field_info, $column, $value); + $query->$operation($field_info, $column, $value, $operator); } return; @@ -315,4 +320,42 @@ class ServicesEntityResourceController extends ServicesResourceControllerAbstrac } } } + + /** + * Filter a query operator. + * + * @param string $operator + * The submitted operator. + * @param mixed $value + * The value to operate on. + * + * @return string + * The filtered operator. + */ + protected function filterOperator($operator, $value) { + $valid_operators = array('=', '<>', '>', '>=', '<', '<=', + 'STARTS_WITH', 'CONTAINS', 'IN', 'NOT IN', + 'BETWEEN', 'LIKE'); + if (in_array(strtoupper($operator), $valid_operators)) { + return $operator; + } + return $this->defaultOperator($value); + } + + /** + * Get the default operator for this value type. + * + * @param mixed $value + * The value to operate on. + * + * @return string + * The default operator. + */ + protected function defaultOperator($value) { + if (is_array($value)) { + return 'IN'; + } + return '='; + } + } diff --git a/plugins/services_entity_resource_clean.inc b/plugins/services_entity_resource_clean.inc index 712ae71..8aefa5b 100644 --- a/plugins/services_entity_resource_clean.inc +++ b/plugins/services_entity_resource_clean.inc @@ -106,13 +106,13 @@ class ServicesEntityResourceControllerClean extends ServicesEntityResourceContro return $this->get_data($wrapper, '*'); } - public function index($entity_type, $fields, $parameters, $page, $pagesize, $sort, $direction) { + public function index($entity_type, $fields, $parameters, $page, $pagesize, $sort, $direction, $options = array()) { $property_info = entity_get_all_property_info($entity_type); $parameters = $this->transform_values($entity_type, $property_info, $parameters); $sort = (isset($property_info['field_' . $sort]))?'field_' . $sort:$sort; // Call the parent method, which takes care of access control. - $entities = parent::index($entity_type, '*', $parameters, $page, $pagesize, $sort, $direction); + $entities = parent::index($entity_type, '*', $parameters, $page, $pagesize, $sort, $direction, $options); foreach($entities as $entity) { $return[] = $this->get_data(entity_metadata_wrapper($entity_type, $entity), $fields); }