It's a little hard to follow your example/description, but I'll take a stab at it.
The way I interpret your question, you need to pull a single guestList
entry that is a) related to the current event
, and b) shares a relationship with the partner
entry set to the current user's partner
field, via a guestAllocation
SuperTable field owned by the event
EntryModel (I'm assuming there's a guestAllocation.partner
column, and that the event section has the event
handle).
The first part is easy, although you seem to be confused about the targetElement
and sourceElement
parameters for the relatedTo
method, so I'll try to clear that up:
Basically, in a relatedTo
query you either specify the target element or the source element (never both) for the relationship – depending on which element owns the field where relation is created.
In your case, the event
entry would be the target element, not the source, as the relatedEvent
field (where the relation is created) belongs to the guestList
entry model, not the event
. In other words, the elements you want (the guest lists) should have the entry you have (the event
entry) selected in a field (i.e. the guestLists
entries "target" the event
entry), not the other way around. If possible, you should also provide the field handle for the field where the relation is created, i.e. relatedEvent
in your case. So, to pull all guestlists related to the current event
entry, the correct relatedTo
query would look like this:
{% set guestListsForEvent = craft.entries.section('guestList').relatedTo({
targetElement: entry,
field: 'relatedEvent'
}) %}
Obviously, you only want one guestlist – the one that is related to the current user's partner
entry (phew!). Trouble is, that relationship doesn't really exist – it's actually more of a condition, where a) the guestList
entry needs to be authored by a user with the correct partner
relation, and b) the current event
needs to have the correct partner
entry (i.e. the current user's related partner
entry) in its guestAllocations
SuperTable field.
The second part is easy – you can set a canCurrentUserCreateGuestList
flag inside a loop on the current event
entry's guestAllocations
field; if the correct partner
event is found in the latter, the current user can create a new guestList
entry and you should also query for an existing guestList
entry:
{% set currentPartner = currentUser.partner.first %}
{% set currentUserCanCreateGuestList = false %}
{% for row in entry.guestAllocation %}
{% if row.partner|length and row.partner.first.id == currentPartner.id %}
{% set currentUserCanCreateGuestList = true %}
{% endif %}
{% endfor %}
Once you have that flag, you can use it in a conditional:
{% if currentUserCanCreateGuestList %}
{# Query for existing guest list, create new list etc #}
{% endif %}
For the latter – the actual query to pull the guestList
entry – a single relatedTo
call obviously won't do the job here, but fortunately the workaround is quite simple – keeping in mind that you need to make sure that a) only 1 guestList
entry is returned, and b) that entry is authored by a user with the same partner
entry as the current user.
Again, the first part is easy – simply use limit
and first
to pull a single entry (I like to add a |default(false)
filter to suppress errors if no entries are returned).
For the second part, you'll first need a list of user IDs for all the users that are related to the current user's partner
entry, and then feed that array to the authorId
parameter for the craft.entries
call:
{# Get the IDs for all users related to the correct partner #}
{% set partnerUserIds = craft.users.relatedTo({
targetElement: currentUser.partner.first,
field: 'partner'
}).ids() %}
{# Get existing partner guest list related to the current event #}
{% set partnerGuestList = partnerUserIds|length ? craft.entries.section('guestList').relatedTo({
targetElement: entry,
field: 'relatedEvent'
}).authorId(partnerUserIds).limit(1).first|default(false) : false %}
The above code will return either a single guestList
EntryModel
, or false
, if no related guestlist entries authored by a user with the correct partner
entry exists. Whether or not the event
entry has the current user's partner
entry in one of its SuperTable guestAllocation.partner
columns is irrelevant to the query itself, once you've established that the current event
does indeed include the correct partner
entry in its guestAllocations
field (the conditional above).
Here's how the whole thing could look in context:
{# Can the current user create a guest list for this event? #}
{% set currentPartner = currentUser.partner.first %}
{% set currentUserCanCreateGuestList = false %}
{% for row in entry.guestAllocation %}
{% if row.partner|length and row.partner.first.id == currentPartner.id %}
{% set currentUserCanCreateGuestList = true %}
{% endif %}
{% endfor %}
{# Get existing guest list #}
{% set partnerGuestList = false %}
{% if currentUserCanCreateGuestList %}
{# Get the IDs for all users related to the correct partner #}
{% set partnerUserIds = craft.users.relatedTo({
targetElement: currentUser.partner.first,
field: 'partner'
}).ids() %}
{# Get existing partner guest list related to the current event #}
{% set partnerGuestList = partnerUserIds|length ? craft.entries.section('guestList').relatedTo({
targetElement: entry,
field: 'relatedEvent'
}).authorId(partnerUserIds).limit(1).first|default(false) : false %}
{% endif %}
{# Create, edit, etc #}
{% if partnerGuestList %}
{# Edit existing guest list #}
{% elseif currentUserCanCreateGuestList %}
{# Create new guest list #}
{% else %}
{# Do nothing? #}
{% endif %}
Note that the above isn't tested and there's a good chance I misinterpreted your question – but hopefully you'll take something away from it.
Finally, as your question also touches on the correct usage of relatedTo
queries with multiple relation criteria: Your original syntax for the relatedTo
call is close, but when you have multiple relation criteria, you'll need to include either and
or or
as the first parameter, specifying if all or any of the criteria should be met, respectively.
In your case, this means the syntactically correct multiple relation query for the partner guestlist should look something like this:
{% set partnerGuestList = craft.entries.section('guestList').relatedTo('and',
{ target: entry, field: 'relatedEvent' },
{ targetElement: currentUser.partner.first(), field: 'guestAllocation.partner' }
) %}
Obviously, for reasons already explained the above query will return nothing. There's also the fact that SuperTable fields (in your case, the guestAllocation.partner
field) doesn't actually work with the built-in relations functionality in Craft – meaning that you can never use craft.entries.relatedTo
when the relation is created in a SuperTable field. Instead, SuperTable provides its own method for relation queries, which is explained in this answer. Again, I don't believe a single relatedTo
call is the correct approach for your particular use case, but just wanted to mention it.
Just for funsies – here's how you could use SuperTable's getRelatedElements
method to pull event
entries based on guestAllocation.partner
relations:
{% set partnerEvents = craft.supertable.getRelatedElements({
relatedTo: {
targetElement: currentUser.partner.first,
field: 'guestAllocation.partner'
},
criteria: {
section: 'event'
}
}) %}