Hi,

With some help I can't remember where I got, I´ve written this module a few years ago. Was planning to publish it as a module, but it seems to require a lot of database reads once a lot of registrations exist.

I was just wondering if anyone can help me try to optimize this code? Could it check the user's registrations and check the taxonomy terms, instead of all existing registrations?

<?php

function limit_registrations_by_taxonomy_node_registration_access(){
    //load current node
    $node = menu_get_object('node');
    
    
    if(isset($node->field_type_clinic['und']['0']['tid'])){
        
        //load current taxonomy term
        $currentTaxId = $node->field_type_clinic['und']['0']['tid'];
        
        //get all the nodeid's that contain the taxonomy terms from the current page
        $nodesToCheck = taxonomy_select_nodes($currentTaxId,FALSE,FALSE);
            
        //loop over the taxonomy id's and check for registrations. Return FALSE if any registration is found.
        foreach ($nodesToCheck as &$value) {
            if(_node_registration_user_registered(node_load($value))){
                //dpm("already subscribed for ".$value."!");
                //user should not be able to register
                return FALSE;
                //return $reason = "You can only register for one workshop.";
            }
        }
    }
}

Comments

Jelmer85 created an issue.

rudiedirkx’s picture

What's the goal? What's the setup? Where is this function used? In the page access callback, or in a view, or somewhere else?

It seems like you want to know if the current user is registered to any node with the same tax term as the current node. Correct?

If you know all the field names, you can make 1 query that checks all that, instead of using inefficient api functions. You'd have to fetch all nodes with the current node's tid, join them to all their registrations and check them for the current user's uid. Something like this:

select count(1)
from node n
join field_data_field_type_clinic ftc on ftc.entity_type = 'node' and ftc.entity_id = n.nid and ftc.field_tid = :current_node_tid
join node_registrations nr on nr.nid = entity_id and nr.user_id = :current_user_uid

If you're doing this in a list, you'd not check the user join or node join, and then return a list, so it would still be only 1 query.

So in short: yes, it can always be more efficient, but maybe it's not worth it, because you can't use api functions, and you have to be very strict: exact field names etc. To make it work is up to you. When it becomes a module, let me know.