0

I bought a module on Envato. I've already contacted the developer, but he does not respond. The module outputs some vertical tabs.

enter image description here

They are created with this code.

/**
 * Implements of hook_builder_content_info()
 */
function builder_builder_content_info() {
  $blocks = _block_rehash();
  $contents = array();
  if (!empty($blocks)) {
    foreach ($blocks as $key => $block) {
      $contents[$block['delta']] = array(
        'info' => $block['info'],
        'type' => 'block',
        'group' => t('Block'),
        // This is name of group to collect contents in a tab
        'block_module' => $block['module'],
      );
    }
  }

  // node add content
  $contents['node'] = array(
    'info' => t('Adding existing node'),
    'group' => t('Node'),
  );

  //Custom text
  $contents['custom_text'] = array(
    'info' => t('Custom text'),
    'group' => t('Text'),
  );

  // Custom heading
  $contents['custom_heading'] = array(
    'info' => t('Custom heading'),
    'group' => t('Text'),
    'no_title' => TRUE,
  );
  // Insert image 
  $contents['image'] = array(
    'info' => t('Insert an image'),
    'group' => t('Image'),
  );

  $contents['youtube'] = array(
    'info' => t('Youtube'),
    'group' => t('Video'),
  );
  $contents['vimeo'] = array(
    'info' => t('Vimeo'),
    'group' => t('Video'),
  );

  $contents['icon'] = array(
    'info' => t('Icon'),
    'group' => t('Icon'),
  );
  return $contents;
}

I can rewrite them in my own function, but I have no idea how to remove them. I thought through $contents['custom_text'] but I'm not sure. Of course, I can remove the original code, but I do not like it.

It looks like unset($contents['custom_text']) is working, but can I run this from another file/function?

EDIT

/**
 * Implements HOOK_builder_content_info_alter()
 */
function builder_gc_builder_content_info_alter(&$contents) {
    unset($contents['node']);
}
3

The function you are showing is an implementation of hook_builder_content_info(). Without seeing the code that calls that hook, I cannot answer about removing the vertical tabs, but I can just give some hints.

If the module also invokes hook_builder_content_info_alter(), which is normally done from the majority of the Drupal modules using hooks, you can implement hook_builder_content_info_alter() in a module.

/**
 * Implements hook_builder_content_info_alter()
 */
function builder_gc_builder_content_info_alter(&$contents) {
  unset($contents['node']['group']);
}

The alter hook could get other arguments, but the structure to change is always the first.

If the module doesn't invoke any hook_builder_content_info_alter() you need to:

  • Avoid Drupal invokes builder_builder_content_info()
  • Implement hook_builder_content_info() using the same code used by builder_builder_content_info() but without those parts that you don't want

This can be done with the following code.

function builder_gc_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'builder_content_info') {
    // Remove the implementation done from that module.
    unset($implementations['builder']);
  }
}

function builder_gc_builder_content_info() {
  $blocks = _block_rehash();
  $contents = array();
  if (!empty($blocks)) {
    foreach ($blocks as $key => $block) {
      $contents[$block['delta']] = array(
        'info' => $block['info'],
        'type' => 'block',
        'group' => t('Block'),
        // This is name of group to collect contents in a tab
        'block_module' => $block['module'],
      );
    }
  }

  // node add content
  $contents['node'] = array(
    'info' => t('Adding existing node'),
  );

  //Custom text
  $contents['custom_text'] = array(
    'info' => t('Custom text'),
    'group' => t('Text'),
  );

  // Custom heading
  $contents['custom_heading'] = array(
    'info' => t('Custom heading'),
    'group' => t('Text'),
    'no_title' => TRUE,
  );
  // Insert image 
  $contents['image'] = array(
    'info' => t('Insert an image'),
    'group' => t('Image'),
  );

  $contents['youtube'] = array(
    'info' => t('Youtube'),
    'group' => t('Video'),
  );
  $contents['vimeo'] = array(
    'info' => t('Vimeo'),
    'group' => t('Video'),
  );

  $contents['icon'] = array(
    'info' => t('Icon'),
    'group' => t('Icon'),
  );
  return $contents;
}

The code I am showing should avoid the information is shown in vertical tabs, but it doesn't avoid the vertical tabs are created. The only way to be sure is to alter the function that invokes hook_builder_content_info(). Using hook_builder_content_info_alter(), you are sure to alter the value returned from all the hook_builder_content_info() implementations, while the other snippet I shown just alters the value returned from a module. If there are two modules passing 'node' as group, the vertical tab will be created, since I am not altering what returned from the other module.

Also, the code I am showing removes the 'group' property, which I am guessing sets the vertical tab where the information is shown, similarly to the #group property used by fieldsets.

Alternatively, you can use the following code, which removes completely the information about the part you don't want to see.

// Case 1.

/**
 * Implements hook_builder_content_info_alter()
 */
function builder_gc_builder_content_info_alter(&$contents) {
  unset($contents['node']);
}
// Case 2. 

function builder_gc_module_implements_alter(&$implementations, $hook) {
  if ($hook == 'builder_content_info') {
    // Remove the implementation done from that module.
    unset($implementations['builder']);
  }
}

function builder_gc_builder_content_info() {
  $blocks = _block_rehash();
  $contents = array();
  if (!empty($blocks)) {
    foreach ($blocks as $key => $block) {
      $contents[$block['delta']] = array(
        'info' => $block['info'],
        'type' => 'block',
        'group' => t('Block'),
        // This is name of group to collect contents in a tab
        'block_module' => $block['module'],
      );
    }
  }

  //Custom text
  $contents['custom_text'] = array(
    'info' => t('Custom text'),
    'group' => t('Text'),
  );

  // Custom heading
  $contents['custom_heading'] = array(
    'info' => t('Custom heading'),
    'group' => t('Text'),
    'no_title' => TRUE,
  );
  // Insert image 
  $contents['image'] = array(
    'info' => t('Insert an image'),
    'group' => t('Image'),
  );

  $contents['youtube'] = array(
    'info' => t('Youtube'),
    'group' => t('Video'),
  );
  $contents['vimeo'] = array(
    'info' => t('Vimeo'),
    'group' => t('Video'),
  );

  $contents['icon'] = array(
    'info' => t('Icon'),
    'group' => t('Icon'),
  );
  return $contents;
}

If this code doesn't work, you could follow the following steps, in order to change the module behavior:

  • Check which function is invoking hook_builder_content_info()
  • Verify if there is a reference to that function in one of the hooks Drupal uses (e.g. hook_menu()); the reference could be either direct or indirect (i.e., the reference is for a function that calls the function invoking hook_builder_content_info())
  • If this is the case, using the alter hook Drupal uses (e.g. hook_menu_alter()), you can change that reference with a reference to a function you write, which uses the code the original function uses, without the part you don't want.

In this way, you aren't directly altering the values returned from hook_builder_content_info(), and you need to copy more of the code used from the module for which you are altering the behavior; this is also means that, for every minimal change in the module you bought, you need to check your code to be sure it doesn't alter the expected behaviour.

  • I can't find a _content_info_alter() in the module. So I tried the second option, but with no luck. My function: builder_gc_builder_content_info() has only two tabs, they are extra added. The others are not removed. – honline Jun 26 '16 at 11:38
  • 1
    @honline the alter function does not have to exist in the module (in most cases a module does not alter it's own definitions as that would be a waste of processing). The alter functions are called from drupal_alter, so in the code you might find something like drupal_alter('content_info', &$contents);. Give the first option a try, it might just work. – Neograph734 Jun 26 '16 at 12:22
  • 1
    Please have a look at the pattern kiamlaluno posted. It should be in the form of mymodule_builder_content_info_alter. you are free to choose the first part, but it must end in _builder_content_info_alter for the pattern to match and the function to be called. UPDATE, just noticed that was your second function. You also must clear the cache for the function to be detected. – Neograph734 Jun 26 '16 at 12:30
  • 1
    @honline I missed an underscore in the function name; that is why it was probably not working. I will update my code to use the module name you are using. – kiamlaluno Jun 27 '16 at 12:40
  • 1
    @honline As long as it's a hook implementation, it works. In other words, if the function is invoked with module_invoke() or module_invoke_all(), it works. Those are the functions used to invoke a hook implementation. They are also used to quickly call a function without to first check the function exists, but I would not count on that. It's better to assume they are used only for hook implementations. – kiamlaluno Jun 27 '16 at 13:13

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.