Hi everyone,

like stefan.r suggested, I am creating this issue to add an option to the recent resolution of #1470530: Unpublish/Delete nodes not included in feed.

Problem/Motivation

My problem is quite simple to understand : I want to reproduce the content of a distant folder with nodes in my Drupal instance. But, when my feed importer checks that folder and the response is empty, nodes are not deleted resulting in a bunch of nodes in Drupal that are no longer wanted.

Proposed resolution

Add an option when the node processors' settings "Delete non-existent nodes" is selected. It could be a checkbox like "Delete nodes even if feed is empty".

Remaining tasks

Well, I guess that's the approval of this issue.

User interface changes

A checkbox in the node processors' settings page

Original report by MegaChriz

MegaChriz explained quite well why this behavior is normal for a large part of feeds users but I think adding this would be great to achieve the previous 2,5 years work :)

Thank you.

Comments

jtronchon’s picture

Issue summary: View changes
jtronchon’s picture

Issue summary: View changes
rudetrue’s picture

Thanks for spotting my duplicate issue. https://www.drupal.org/node/2553331

I wonder if there are others having the same issue, it's kind of hard to find the exact cause because it isn't consistent (everything works as expected until the feed is completely empty).

Also, I was thinking about it more, and it would be nice to not even have the "Delete nodes even if feed is empty" setting. I'm not familiar with the code, but to me it makes sense that if the request to get the feed is an HTTP 200, and the parser doesn't throw an exception, all content that was imported should be deleted/unpublished. The UI is already complicated, I say default to removing the nodes unless there's an obvious error.

jtronchon’s picture

It's not complicated. If you check my comment right here you'll see that it's not a huge problem. In #210, stephan.r make a cleaner version. I tried to make this title the more understandable and searchable in order to help those who are seeking this functionality.

Yeah maybe the checkbox is not a good solution... Since I'm not the only one seeking this anymore, I guess we could try to figure out what is best to do.

wrobins’s picture

For now, if anyone is interested in the checkbox solution for their project, this should do the trick.

megachriz’s picture

Status: Active » Needs review

Setting to "Needs review" so the testbot will evaluate the patch.

Status: Needs review » Needs work

The last submitted patch, 5: feeds-delete_if_empty_source-2333667-5.patch, failed testing.

johnpicozzi’s picture

I have tweaked the patch above to work with the latest dev release. Please review and test accordingly.

johnpicozzi’s picture

Status: Needs work » Needs review

Setting to "Needs review" so the testbot will evaluate the patch.

megachriz’s picture

Issue tags: +Needs tests

It would be great to have an automated test for this feature.

ndf’s picture

Quoting MegaChriz https://www.drupal.org/node/1470530#comment-9120655

@AndrackOSnack
I noticed back in #181 too that no items are deleted/unpublished when the source is completely empty, but I would say this is intentional. I think that it is rare to be wanting to import a blank source. For example, it could happen that something went wrong during fetching the source, ultimately resulting in a blank source. You don't want all items to be deleted in such case.

It depends.
If the fetcher has no results due to an error, then I think this is true. Note that the Fetcher plugins will throw Exceptions in case of a failed download.
If the fetcher is working properly but there are no results, shouldn't deleting/unpublishing be default behaviour?

So my proposal would be to drop "delete_if_empty" setting (or make it default) and trust on a catched Exception in FeedsFetcher. That should stop the FeedsProcessor from removing/unpublishing nodes in case of an error.

moriartyluck’s picture

We definitely need this functionality. We use it to show alerts published from an incident management tool. When all alerts are cleared, we need the alerts to be unpublished without manual intervention. We have other checks in place to ensure the feed is not broken.

megachriz’s picture

@lauren.moriarty
If you can provide an automated test for this feature, I'll add it to the module.

@ndf
If a download fails, it *could* be that the import stops and nothing gets deleted. But in that case that would also require tests to ensure unwanted deletions do not happen. We would for example need to test what happens if the source returns a 404. And what happens if the source has a WSOD and returns a complete blank page.
A setting will be safer.

aporie’s picture

#8 worked for me but the title "Delete items even if source feed is empty" is a bit misleading.

Something like "Execute action if the source is empty" or something like that should be more clear, as it actually executes the configuration you chose in "update-non-existent".

xlin’s picture

StatusFileSize
new1.54 KB

Updated #8 to make wording more generic.

xlin’s picture

StatusFileSize
new1.54 KB

Reverse the checkbox default so that process empty source is off by default. When using this option, it is important to validate that you feeds is actually empty. not because of network or source change or other factors.

e.g One way would be use hook_feeds_after_parse().

function my_module_bedework_feeds_after_parse(FeedsSource $source, FeedsParserResult $result) {
  if ($source->id == 'my_events') {
    $events = $result->items;
    if (empty($events)) {
      $raw_response = $source->fetcher_result->getRaw();
      $json = json_decode($raw_response);
      if (!isset($json->keytocheck)) {
        $config = $source->importer->processor->getConfig();
        $config['process_empty'] = FALSE;
        $source->importer->processor->setConfig($config);
      }
    }
ethomas08’s picture

StatusFileSize
new1.65 KB

Re-rolled patch for the latest 7.x-2.x release

plektr0’s picture

Version: 7.x-2.x-dev » 7.x-2.0-beta5
Status: Needs review » Reviewed & tested by the community
megachriz’s picture

This does still require an automated test.

epersonae2’s picture

Is anyone working on this feature for Drupal 8?

oppure’s picture

Hi
I suggest that the FeedsResult class shoud have an attribute to store error codes at both fetching and parsing stages so they can be passed on to the processor, so that a processor can make an "informed" decision on where it is appropriate to delete all items when the feed is empty, e.g. if the httpfetcher downloads an empty rss xml document with http status code 200 then the parser correctly parses it as empty (so error code is "no error") then the processor could know that the feed is actually empty with no errors and delete all items (if user selected the option), if either the fetcher or the parser returned an error then it would instead keep all items and log a warning to alert the admin that something was wrong with that feed.

Thank you for the fantastic module and regards.

nathan tsai’s picture

Crossposting from https://www.drupal.org/project/feeds/issues/3337811#comment-15145862:

If looking for a work around so that feeds will unpublish missing nodes even when the response is empty...

Set your importer to include the published status.

Then use the following code to ensure there's always at least one node in your response.

...I did not realize that feeds do not import nodes when the response is empty or there are no items.

For future reference, I added the following code for my REST Export to ensure there is always at least one item in my response.

use Drupal\views\ViewExecutable;
use Drupal\views\ResultRow;
use Drupal\node\Entity\Node;

/**
 * Implements hook_views_post_execute().
 */
function HOOK_views_post_execute(ViewExecutable $view) {
  if ($view->id() == 'MY_VIEW_ID') {
    // Feeds does not import an empty response. Therefore, add a dummy feeds item.
    // @see https://www.drupal.org/project/feeds/issues/2333667#comment-15145873
    if ($view->total_rows === 0) {
      $dummyNode = Node::create([
        'type' => 'job_posting',
        'nid'  => -1, // Our GUID. This is valid because we never save the node
        'title' => 'PLACEHOLDER NODE',
        'status' => 0, // Be unpublished, so it doesn't appear on the importing website
      ]);
      $view->result[] = new ResultRow([
        '_entity' => $dummyNode,
      ]);
    }
  }
}
bluegeek9’s picture

Status: Reviewed & tested by the community » Closed (outdated)
//www.flaticon.com/free-icons/thank-you Thank you for your contribution!

Unfortunately, Drupal 7 is End of Life and no longer supported. We strongly encourage you to upgrade to a supported version of Drupal.

Now that this issue is closed, review the contribution record.

As a contributor, attribute any organization that helped you, or if you volunteered your own time.

Maintainers, credit people who helped resolve this issue.