Ran into an interesting problem when importing a feature module that includes search api during a profile install. The install runs correctly up to filling out the site information form, but then I receive the below error after submitting the form. It's obviously occurring when the cron job is running:
( ! ) Fatal error: __clone method called on non-object in E:\Work\drupal\public_html\profiles\bir_profile\modules\contrib\search_api\search_api.module on line 1044
Call Stack
# Time Memory Function Location
1 0.0009 341704 {main}( ) ..\install.php:0
2 0.0013 342032 install_drupal( ) ..\install.php:26
3 0.2824 683992 install_run_tasks( ) ..\install.core.inc:77
4 24.8736 69354656 install_run_task( ) ..\install.core.inc:339
5 24.8736 69354656 install_finished( ) ..\install.core.inc:470
6 30.5987 70148936 drupal_cron_run( ) ..\install.core.inc:1527
7 38.2370 69987728 _search_api_indexing_queue_process( ) ..\common.inc:5243
8 38.2950 70017992 search_api_index_specific_items( ) ..\search_api.module:2142
I tracked it down to the foreach loop in the search_api_index_specific_items() function
foreach ($items as $id => $item) {
$cloned_items[$id] = clone $item;
}
During the features import, some static node pages (nids 1 through 72) are added to the node table. The "$items" contain these nodes. However, the last node (nid = 72) is empty. I found this out by running the install profile again, printing out the $id and $item in the above loop before it is cloned. All the nodes in the database print out except nid 72. I see the 72 printed out, but no object data. Which makes sense since it throws the error. There is nothing different about node 72 in the database, as it is a static page much like the others.
As an experiment, I checked for $item being an object before cloning:
foreach ($items as $id => $item) {
if (is_object($item) {
$cloned_items[$id] = clone $item;
}
}
The install profile worked without any errors doing this. So I then checked the index status in the newly installed site:
About 98% of all items have been indexed in their latest version (71 / 72).
Again, makes sense given I'm bypassing the empty node object with the above object check.
What does not make sense is why those nodes are being indexed. My index is filtered by bundle type:
Enabled data alterations
Bundle filter checked
Exclude items from indexing based on their bundle (content type, vocabulary, …).
.....
In the callback settings from the same page, I have "Only those from the selected bundles" selected, with only the bundles I want indexed (pages, book, and news not being any of them). If I clear the index and re-index via the Status page, all 72 nodes are indexed.
Questions:
So why are these nodes being indexed when they shouldn't? Or am I misreading the "Enabled data alterations" setting and what it does?
How can I figure out why nid 72 is empty during the profile install?
Perhaps Search API can't be included in Feature export?
Is it a good idea to check for "$item" being an object before attempting to clone, adding a watchdog in an "else" so an admin is at least warned, but the process does not fail?
Any suggestions would be appreciated.
| Comment | File | Size | Author |
|---|---|---|---|
| #6 | 1902168-6--avoid_cloning_non-object.patch | 1.13 KB | drunken monkey |
| #1 | search_api-clone_method_on_non_object-1902168-1.patch | 557 bytes | mpv |
| #1 | search_api-clone_method_on_non_object-7.x-1.7-1902168-1.patch | 557 bytes | mpv |
Comments
Comment #1
mpv commentedThank you! I had the same error on 7.x-1.7 but your code fixed it. I've made it into a patch against 7.x-1.7 and 7.x-1.x-dev. I don't know if this is a fix or a dirty workaround, but it's working for me.
Comment #2
drunken monkeyFor determining the bundle, and thus whether the node should be included, the node has still got to be loaded beforehand. See #1184610: Limit indexes to specific entity bundles for a discussion about possibly changing this.
Regarding the issue itself, I'm a bit baffled as to what could cause this behavior – but I guess a lot of weird stuff happens during installation. If it's easily possible, could you maybe find out what
$itemis when it isn't an object, and what it contains (if anything)? Maybe that will lead us to the root of the problem.Having said that, though, I don't have any objection to committing this workaround/fix either. It's trivial enough, after all, and if it helps a few users …
So, just waiting for a response on the debugging request, then I think we can just commit this.
In any case, thanks for reporting this issue and providing a fix right with it!
Comment #3
mpv commentedThe first time
search_api_index_specific_itemsis called during install I haveand the second time
In both cases
$objectisint(1).Node 1 is a webform exported in a feature with uuid. Im using search_api_db as the backend.
Hope it helps.
Comment #4
drunken monkeyOK, thanks. That practically means there is a bug in another module (either Webform or UUID or whatever), since an
entity_load()should never return just the ID – either a successfully loaded object or nothing at all. Whatever substitutes the node entity controller (or does some weird things in a load hook) has to be buggy.(The backend shouldn't play any role here.)
Still, we should probably commit this little fix in any case, and maybe someone finds the time to debug this further and create an issue in the appropriate queue. (Basically, just find a custom node entity controller implementation in one of your modules, or a complex
hook_node_load().)Comment #5
mpv commentedI agree. Even if the module that is causing this error is fixed it's safer to have the check I think. Changing to RTBC.
Thanks for taking the time to review this.
Comment #6
drunken monkeyNo problem.
The patch lacked a
watchdog()call in the error case, though, and a bit of explanation.Revised patch attached, please also test/review!
Comment #7
mpv commentedYour last patch worked great, so changing to RTBC. The installation ended without errors and the message was added to the log.
Comment #8
drunken monkeyExcellent, good to hear.
Committed. Thanks again!