How to override a hook from another plugin

I am trying to override the following from the wire tools plugin (https://elgg.org/plugins/1608487) with my own plugin. 

thewire_tools/start.php

elgg_register_plugin_hook_handler("access:collections:write", "all", "thewire_tools_access_write_hook", 999);

thewire_tools/lib/hooks.php

function thewire_tools_access_write_hook($hook_name, $entity_type, $return, $params) {
    
    if (!elgg_in_context("thewire_add")) {
        return $return;
    }
    
    if (empty($return) || !is_array($return)) {
        return $return;
    }
    
    if (empty($params) || !is_array($params)) {
        return $return;
    }
    
    $user_guid = (int) elgg_extract("user_id", $params, elgg_get_logged_in_user_guid());
    if (empty($user_guid)) {
        return $return;
    }
    
    // remove unwanted access options
    unset($return[ACCESS_PRIVATE]);
    unset($return[ACCESS_FRIENDS]);
    
    // add groups (as this hook is only trigged when thewire_groups is enabled
    $options = array(
        "type" => "group",
        "limit" => false,
        "relationship" => "member",
        "relationship_guid" => $user_guid,
        "joins" => array("JOIN " . elgg_get_config("dbprefix") . "groups_entity ge ON e.guid = ge.guid"),
        "order_by" => "ge.name ASC"
    );
    
    $groups = new ElggBatch("elgg_get_entities_from_relationship", $options);
    foreach ($groups as $group) {
        if ($group->thewire_enable !== "no") {
            $return[$group->group_acl] = $group->name;
        }
    }
    
    return $return;
}

I unregistered the hook correctly but when I try to register the hook to override it is not working. How can specify the location of the hook so it can use the one in my_plugin/lib/hooks.php when I re-register it in my_plugin?

my_plugin/start.php

elgg_unregister_plugin_hook_handler("access:collections:write", "all", "thewire_tools_access_write_hook");
elgg_register_plugin_hook_handler("access:collections:write", "all", "thewire_tools_access_write_hook", 999);

my_plugin/lib/hooks.php

function thewire_tools_access_write_hook($hook_name, $entity_type, $return, $params) {
    
    if (!elgg_in_context("thewire_add")) {
        return $return;
    }
    
    if (empty($return) || !is_array($return)) {
        return $return;
    }
    
    if (empty($params) || !is_array($params)) {
        return $return;
    }
    
    $user_guid = (int) elgg_extract("user_id", $params, elgg_get_logged_in_user_guid());
    if (empty($user_guid)) {
        return $return;
    }
    
    //I want to allow users to select private and friends as well.
    //unset($return[ACCESS_PRIVATE]);
    //unset($return[ACCESS_FRIENDS]);
    
    // add groups (as this hook is only trigged when thewire_groups is enabled
    $options = array(
        "type" => "group",
        "limit" => false,
        "relationship" => "member",
        "relationship_guid" => $user_guid,
        "joins" => array("JOIN " . elgg_get_config("dbprefix") . "groups_entity ge ON e.guid = ge.guid"),
        "order_by" => "ge.name ASC"
    );
    
    $groups = new ElggBatch("elgg_get_entities_from_relationship", $options);
    foreach ($groups as $group) {
        if ($group->thewire_enable !== "no") {
            $return[$group->group_acl] = $group->name;
        }
    }
    
    return $return;
}

 

  • Rename your function. It doesn't have to have the same name.

  • Ismayil,

    I renamed the function but no luck. How do I tell it, use the function of an specific location? 

  • elgg_unregister_plugin_hook_handler("access:collections:write", "all", "thewire_tools_access_write_hook");

    elgg_register_plugin_hook_handler("access:collections:write", "all", "myplugin_access_write_hook", 999);

    Then:

    function myplugin_access_write_hook($hook, $type, $return, $params) {

    Stick some error logging in your function while testing to ensure it's getting called.

  • Matt,

    Thanks a lot. It is working correctly by adding the function to the same start.php file, nothing wrong with that, but I am still curious on how to tell it, use the function from the following location. 

  • I'm not sure what you mean... you can't redeclare a function with the same name.

  • Matt, 

    what I meant was this. 

    The hook is registered in the plugin's start.php file and the function is also the in the same start.php, this way the function is being overridden. 

    Some plugins have their functions or hook handlers in a different place and not the start.php file, for example, thewire_tools/lib/hooks.php. I tried renaming the function in myplugin/lib/hooks.php file but it did not work. 

    My question is, if we want to override a function by keeping the same path structure in your plugin ( myplugin/lib/hooks.php), is there an specific way of doing it?

    The example below was taken from the thewire_tools/start.php file

     // overrule default save action
    
            elgg_unregister_action("thewire/add");
    
            elgg_register_action("thewire/add", dirname(__FILE__) . "/actions/thewire/add.php");
    
            elgg_register_action("thewire_tools/mentions_upgrade", dirname(__FILE__) . "/actions/upgrades/mentions.php");

    The latter is overriding an action by specifying the path. How can we do the same for a hook handler?

    thewire_tools plugin is using require_once(dirname(__FILE__) . "/lib/hooks.php"); when I tried to use the same in myplugin start.php file, it breaks the entire site. LOL.

    Although I already accomplished what I wanted with your suggestion, this is like a small pebble in your shoe, you can leave with it, but it bothers you. XD.

  • You can't do the same for the hook handler, because hook handlers don't use paths, they use named functions.  Only actions use paths.

    When you required lib/hooks.php I think you had the same function name declared in there (based off your previous replies) - so it would kill the site due to a redeclaration fatal error.