function node_type_delete($type) {
  $info = node_type_get_type($type);
  db_delete('node_type')
    ->condition('type', $type)
    ->execute();
  field_attach_delete_bundle('node', $type);
  module_invoke_all('node_type_delete', $info);

node_type_get_type() does not returns info for a node_type tagged as disabled, it will $info=FALSE. This behavior is due to _node_types_build().

Use of $info=FALSE will make hook_node_type_delete fail.

Typically, node_type_delete is called during hook_uninstall, when the node_type has already tagged as disabled

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

jpsoto’s picture

Status: Active » Needs review
FileSize
1.14 KB

This patch should solve the bug ...

sun.core’s picture

#1: 943588_101023.patch queued for re-testing.

jpsoto’s picture

#1: 943588_101023.patch queued for re-testing.

pillarsdotnet’s picture

Marked #995756: Trying to get property of non-object as a dup of this issue.

jpsoto’s picture

#1: 943588_101023.patch queued for re-testing.

pillarsdotnet’s picture

FileSize
737 bytes

Same patch, minus the name change.

jpsoto’s picture

Status: Needs review » Reviewed & tested by the community

@pillarsdotnet, thanks for your review and support ... I think issue status can be evolved.

I described a similar (but different) behavior for fields-related functions: #943772: field_delete_field() and others fail for inactive fields

webchick’s picture

Status: Reviewed & tested by the community » Needs work
Issue tags: +Needs tests

We should add tests for this I think.

jpsoto’s picture

@webchick ... OK, I will add the related tests ... using the last patch #6

pillarsdotnet’s picture

Status: Needs work » Needs review
FileSize
742 bytes

Typo in #6; correcting...

pillarsdotnet’s picture

Status: Needs review » Needs work
jpsoto’s picture

Status: Needs work » Needs review
FileSize
2.91 KB

Friends ... attached you can find the patch including two additional tests: deletion of a node type, and deletion of a disabled node type.

The second test would fail in the present Drupal core, but it is passed using the patch. Local testing has been carried out.

[patch includes the Pillarsdotnet's contributions]

Please, take a look at a other issue, with similar (but different) behavior for fields-related functions: #943772: field_delete_field() and others fail for inactive fields

pillarsdotnet’s picture

I understand changing the parameter name away from $type so as to avoid visual confusion with the array $types but calling it "$bundle_name" is also confusing, as it conflicts both with the documentation and with the naming convention used in other, similar functions in core.

How about compromising by calling it $type_name instead of $bundle_name?

Status: Needs review » Needs work
Issue tags: -Needs tests

The last submitted patch, node_type_delete-943588-13.patch, failed testing.

pillarsdotnet’s picture

Status: Needs work » Needs review
Issue tags: +Needs tests

#13: node_type_delete-943588-13.patch queued for re-testing.

jpsoto’s picture

Status: Needs review » Reviewed & tested by the community

@pillarsdotnet, thanks for your suggestions ...

friends, ... ihmo, issue status can be evolved ...

Taxoman’s picture

Subscribing.

bfroehle’s picture

Status: Reviewed & tested by the community » Needs work
+++ modules/node/node.moduleundefined
@@ -614,16 +614,20 @@ function node_field_extra_fields() {
-function node_type_delete($type) {
-  $info = node_type_get_type($type);
+
+function node_type_delete($type_name) {

There is an extra line between the docblock and the function. Also, I disagree with changing the argument name -- $type is fine and is consistent with other functions (like "node_type_update_nodes($old_type, $type)", for example). But whatever.

+++ modules/node/node.testundefined
@@ -1141,14 +1141,25 @@ class NodeTypeTestCase extends DrupalWebTestCase {
+    db_query("UPDATE {node_type} SET disabled = TRUE WHERE type = :type", array(':type' => $type->type));

Rewrite this using db_update().

+++ modules/node/node.testundefined
@@ -1141,14 +1141,25 @@ class NodeTypeTestCase extends DrupalWebTestCase {
+    $this->assertFalse($type_exists, 'A disabled content type has been deleted from the database.');
+    ¶
     // Login a test user.
+    $type = $this->drupalCreateContentType();
     $web_user = $this->drupalCreateUser(array('create ' . $type->name . ' content'));
     $this->drupalLogin($web_user);
 

Extra white space on this line.

Powered by Dreditor.

bfroehle’s picture

Status: Needs work » Needs review
FileSize
1.75 KB

Another bigger problem is that the added tests do not trigger the bug.

bfroehle’s picture

Status: Needs review » Needs work
jpsoto’s picture

@bfroehle
please, feel free to complete the works ... This bug is open long long time ago and now I am quite busy.

jpsoto’s picture

Status: Needs work » Needs review
FileSize
2.7 KB

Rollback using an updated git diff ... trying testing

pillarsdotnet’s picture

FileSize
2.06 KB

Testing-only version of above patch.

(Tests of a bugfix, without the bugfix, should fail)

pillarsdotnet’s picture

Status: Needs review » Needs work

Once again, tests pass without the fix, so the tests are not effective.

jpsoto’s picture

@pillarsdotnet
I beg your pardon ... I am not able to understand what you are suggesting ...

Please, feel free to merge or complete my patch ...

bfroehle’s picture

@jpsoto: What @pillarsdotnet is saying is that the test routines are not sufficient to trigger the bug. That is, without any patch to Drupal's behavior, all of the test routines pass. Essentially the test routines have failed to trigger the bug, and thus are insufficient.

jpsoto’s picture

OK ... now I understand ... thanks.

Let me a couple of days, to setup a sensible test proving the bug.

jpsoto’s picture

OK ... after a preliminary review, I have found out a significant change since patch and test codes were written (over six months ago).

Now, when a module (which created a node type) is disabled, such a node type is *not* marked as disabled. Direct DB inspection reveals it; disabled remains FALSE, at least for me.

Seemingly, such a behavior should be not correct because the field "disabled" seems to be used for several tasks.

I am not able to remember if, in October, the field "disabled" were toggled by module_enable() / module_disable(). And my skills to dig into the git log are limited.

Any way, ... this could explain why now the tests are not able to reproduce the bug. Or even more, this could explain why the bug could have disappeared (or rather mutated).

Does anybody know if the field "disabled" of an node type is in use, or is to be removed in the future?

What about closing this issue?

pillarsdotnet’s picture

Status: Needs work » Closed (duplicate)

It looks like this behavior was changed by this commit which came from this patch.

Types which are not provided by hook_node_info() are no longer disabled by node_types_rebuild().

Marking this issue as a duplicate of #986296: _node_types_build() accidentally marks node types as disabled because even though the symptoms are different, the cause (and fix) appear to be the same.

rbruhn’s picture

Sorry if this is the wrong place to post. I've chased through all sorts of issues about node content being left behind and this seems the closest to what I'm experiencing.
I'm defining a custom node in hook_install() with 'base' => 'bir_collection'. When going through the process of uninstalling, I get errors:

Notice: Trying to get property of non-object in comment_node_type_delete()

This only occurs when base is set to a custom type. If 'node_content' is used, no errors occur when uninstalling. This is due to the node type NOT being set as 'disabled' when base is 'node_content'.
Tracing this back, it can be seen the disabled node type is not picked up in _node_types_build().

// in hook_uninstall() for module
node_type_delete('bir_collection');

// Line 618: node.module
function node_type_delete($type) {
  $info = node_type_get_type($type);
  db_delete('node_type')
    ->condition('type', $type)
    ->execute();
  field_attach_delete_bundle('node', $type);
  module_invoke_all('node_type_delete', $info);

  // Clear the node type cache.
  node_type_cache_reset();
}

// Line 401: node.module
function node_type_get_type($node) {
  $type = _node_extract_type($node);
  $types = _node_types_build()->types;
  return isset($types[$type]) ? $types[$type] : FALSE;
}

Performing tests by calling _node_types_build()->types in a script shows the custom node type is not returned when disabled. So after disabling and trying to uninstall, the $info variable in module_invoke() is empty. Thus, causing the error posted above.

Am I missing something here in my uninstall hook? Should node_type_delete() not be used for node types created in modules?

Edit:
Found #1181030: Node types disabled by _node_types_build() when using node_type_save() with base != 'node_content' speaking about the same issue. Funny, because all these issues link back to one another but the problem still remains.

realguess’s picture

My solution is that just temporarily enable the node type in hook_uninstall, then proceed to delete the node type.

  // Temporarily enable the node type
  db_update('node_type')
    ->fields(array(
      'disabled' => 0,
    ))
    ->condition('type', 'bir_collection', '=')
    ->condition('disabled', 1, '=')
    ->execute();

  // Clear the node type cache
  node_type_cache_reset();

  // Delete node type
  node_type_delete('bir_collection');

Not a solution I like, I think node_type_delete should be able pick up the disabled node types. But this will get rid of error messages from other modules that implements hook_node_type_delete.

rbruhn’s picture

@realguess
Thanks, I will give your solution a try.

duckegg’s picture

@realguess
Good shot! It solves my problem

jonathan1055’s picture

Title: node_type_delete(): hook_node_type_delete will fail for a disabled node_type » node_type_delete(): hook_node_type_delete will fail for a disabled node_type. Trying to get property of non-object in hook_node_type_delete()
Issue summary: View changes

@pillarsdotnet in #29 - thanks for finding that commit. However, the issue we have here is not actually solved by that fix. Our problem is that implementations of hook_node_type_delete in other contrib modules give errors because the $info parameter passed is empty or null.

I have found an alternative solution to the one from realguess in #31. At the start of hook_uninstall, instead of re-enabling the content type, you can call

  node_type_cache_reset();
  node_types_rebuild();

The call to node_types_rebuild() will include the disabled content types and the result will be stored in the cache for the remainder of the page requset, thus any further calls to node_type_get_type() will be able to return the info required. I have used this in Weblinks #2500119: Uninstalling produces error: Trying to get property of non-object in comment_node_type_delete() as we had exactly the same problem.

Hope that helps anyone else who comes across this error.

Jonathan