## Description
Currently type and return_type have rather strict restrictions:
* only one value per request
* they are combined using OR operator
https://www.mediawiki.org/wiki/Extension:WikiLambda/API#wikilambdasearch_labels
However, with persisted Function Calls we have more complex requirements for this API.
These are the use cases which we should be requiring different search patterns:
| use case | expect | allowed return types | what to do with result | query by | manually exclude |
| --- | --- | --- | --- | --- | --- |
| 1. function input or function output | anything that resolves to a Z4 (strict) | Z4, Z8, Z7 | Z4 and Z7: create reference, Z8: create function call | (type = Z4 OR return_type = Z4) | Z6884 |
| 2. function call function (Z7K1) parent type open | any function | Z8 | create reference | (type = Z8) | Z6884 (unless top level) |
| 3. function call function (Z7K1) parent type bound | any function that returns parentType (not strict) | Z8 | create reference | (type = Z8) AND (return_type = parentType OR return_type = Z1) | Z6884 (unless top level) |
| 4. type reference | anything that can be used as a Z4 | Z4, Z7 | create reference | (type = Z4) OR (return_type = Z4 AND type = Z7) | |
**Desired behavior/Acceptance criteria**
* [ ] The filter API is sufficiently flexible to adjust to all our use cases without needing multiple calls
* [ ] The UI requests objects according to the requirements, this includes:
* [ ] `TypeSelector` component
* [ ] `ZReference` component
===An example of current labels table===
| wlzl_zobject_zid | wlzl_type | wlzl_return_type | wlzl_label | etc... |
| --- | --- | --- | --- | --- |
| Z11 | Z4 | NULL | a normal type | |
| Z12 | Z4 | NULL | another normal type | |
| Z801 | Z8 | Z1 | a function that returns anything | |
| Z881 | Z8 | Z4 | a function that returns type | |
| Z866 | Z8 | Z40 | a function that returns boolean | |
| Z6884 | Z8 | Z4 | enum function, returns type | |
| Z10000 | Z7 | Z4 | one persisted enum | |
| Z10002 | Z7 | Z4 | another persisted enum | |
- use case 1: If I want to select a type for function input or output: **Z11**, **Z12**, **Z881**, **Z10000**, **Z10001**, Z6884*
- use case 2: If I want to select a function for a function call Z7K1, and parent type can be anything: **Z801**, **Z881**, **Z866**, Z6884*
- use case 3: If I want to select a function for a function call Z7K1, and parent type is bound to Z4: **Z801**, **Z881**, Z6884*
- use case 4: If I want to select a type for Z1K1 or for Z3K1: **Z11**, **Z12**, **Z10000**, **Z10002**
(zids marked with * will be manually excluded from results, but the query is expected to return them)
===Options===
====Option 1====
1. edit secondary table’s details, add return_type to non-function and on-functioncall objects
2. aggregate type and return_type with an AND operator
**use case 1:**
- type=null
- return_type=Z4
- build sql condition: `WHERE return_type=‘Z4’`
- matches objects: Z11, Z12, Z881, Z6884, Z10000, Z10002
**use case 2 (return type unbound):**
- type=Z8
- return_type=null
- build sql condition: `WHERE type='Z8'`
- matches objects: Z801, Z881, Z866, Z6884
**use case 3 (return type bound):**
- type=Z8
- return_type=[Z4, Z1]
- build sql condition: `WHERE type='Z8' AND return_type IN ['Z4', 'Z1']`
- matches objects: Z801, Z881, Z6884
**use case 4:**
- type IN [Z4, Z7]
- return_type=Z4
- build sql condition: `WHERE type IN [ 'Z4', 'Z7' ] AND return_type='Z4' `
- matches objects: Z11, Z12, Z10000, Z10002
**Pros and cons:**
- ❌ We’d need to run secondary updates for all objects in production
- ✅ **Alternative:** We can build a script that just iterates through the labels table and: if return_type is NULL, set type value
- ✅ **Alternative:** We can avoid this by adding the following logic to the query:
- if return_type is present but type is not, add `OR type = return_type` to the query:
- e.g. type=Z8 and return_type=Z4 would build `SELECT * WHERE type='Z8' AND return_type='Z4'` <-- all parameters present, aggregate conditions with AND
- e.g. **type=null** and return_type=Z4 would build `SELECT * WHERE return_type='Z4' OR type='Z4'` <-- type not present, duplicate the return_type and aggregate with OR
- ✅ Pretty simple changes to API props:
- Make them lists of strings, to be able to do `type IN [ 'Z4', 'Z7' ]` or `return_type IN ['Z4', 'Z1']`
- We could remove strict property, which has always been a bit confusing
====Option 2====
1. Build an advanced filtering system with complex expressions passed as properties
2. Make no changes to the data represented in the secondary table
3. Each caller should know how to build the right filter_expression property
**use case 1: function input/output types**
```
filter_expression = {
"or": [
{ "type": "Z4" },
{ "return_type": "Z4" }
]
}
```
- builds sql condition: `WHERE type='Z4' OR return_type='Z4'`
- matches objects: Z11, Z12, Z881, Z6884, Z10000, Z10002
**use case 2: function call to function (return type unbound)**
```
filter_expression = { "type": "Z8" }
```
- builds sql condition: `WHERE type='Z8'`
- matches objects: Z801, Z881, Z866, Z6884
**use case 3: function call to function (return type bound)**
```
filter_expression = {
"and": [
{ "type": "Z8" },
{
"or": [
{ "return_type": "Z4" },
{ "return_type": "Z1" }
]
}
]
}
```
- builds sql condition: `WHERE type='Z8' AND ( return_type='Z4' OR return_type='Z1' )`
- matches objects: Z801, Z881, Z6884
**use case 4: persisted type or type expression**
```
filter_expression = {
"or": [
{ "type": "Z4" },
{
"and": [
{ "type": "Z7" },
{ "return_type": "Z4" }
]
}
]
}
```
- builds sql condition: `WHERE type='Z4' OR ( type='Z7' AND return_type='Z4' )`
- matches objects: Z11, Z12, Z10000, Z10002
**Pros and cons:**
- ❌ Not sure how ActionAPI can allow this kind of complex parameter
- Could be a JSON encoded as a string
- Could just be an advanced property, but keep type and return_type as they are for backwards compatibility.
- ❓would this be justified? this is an internal API only used by the frontend lookup components, so we can make changes to the signature if we wish
- ✅ This system is infinitely flexible
- ✅ Requires no changes to the database
- ❌ Complexity to use the API (and the ApiSandbox) increases significantly
---
## Completion checklist
* [ ] Before closing this task, review one by one the checklist available here: https://www.mediawiki.org/wiki/Abstract_Wikipedia_team/Definition_of_Done#Front-end_Task/Bug_Completion_Checklist