diff --git a/includes/FeedsSource.inc b/includes/FeedsSource.inc index f5475f1..919eac0 100644 --- a/includes/FeedsSource.inc +++ b/includes/FeedsSource.inc @@ -91,6 +91,11 @@ class FeedsState { public $failed; /** + * IDs of entities to be removed. + */ + public $removeList; + + /** * Constructor, initialize variables. */ public function __construct() { diff --git a/plugins/FeedsNodeProcessor.inc b/plugins/FeedsNodeProcessor.inc index 203685a..656a4cd 100644 --- a/plugins/FeedsNodeProcessor.inc +++ b/plugins/FeedsNodeProcessor.inc @@ -1,5 +1,7 @@ 'select', '#title' => t('Expire nodes'), '#options' => $period, - '#description' => t('Select after how much time nodes should be deleted. The node\'s published date will be used for determining the node\'s age, see Mapping settings.'), + '#description' => t("Select after how much time nodes should be deleted. The node's published date will be used for determining the node's age, see Mapping settings."), '#default_value' => $this->config['expire'], ); + // Add on the "Unpublish" option for nodes, update wording. + if (isset($form['update_non_existent'])) { + array_walk_recursive($form['update_non_existent'], array($this, 'replaceEntitiesByNodes')); + $form['update_non_existent']['#options'][FEEDS_UNPUBLISH_NON_EXISTENT] = t('Unpublish non existent nodes'); + } return $form; } /** + * Callback for array_walk_recursive in $this->configForm() to help update + * wording in the "update_non_existent" form element. + */ + protected function replaceEntitiesByNodes(&$value, &$key) { + $value = str_replace('entities', 'nodes', $value); + } + + /** * Override parent::configFormValidate(). */ public function configFormValidate(&$values) { @@ -363,4 +378,29 @@ class FeedsNodeProcessor extends FeedsProcessor { return 0; } + /** + * Overrides FeedsProcessor::clean() + * Allow unpublish instead of delete. + * + * @param FeedsState $state + */ + protected function clean(FeedsState $state) { + // Delegate to parent if not unpublishing or option not set + if (!isset($this->config['update_non_existent']) || $this->config['update_non_existent'] != FEEDS_UNPUBLISH_NON_EXISTENT) { + return parent::clean($state); + } + + $total = count($state->removeList); + if ($total) { + $nodes = node_load_multiple($state->removeList); + foreach ($nodes as &$node) { + if ($node->status == 0) { + continue; + } + node_unpublish_action($node); + node_save($node); + $state->updated++; + } + } + } } diff --git a/plugins/FeedsProcessor.inc b/plugins/FeedsProcessor.inc index 6666276..5b4be93 100755 --- a/plugins/FeedsProcessor.inc +++ b/plugins/FeedsProcessor.inc @@ -9,6 +9,9 @@ define('FEEDS_SKIP_EXISTING', 0); define('FEEDS_REPLACE_EXISTING', 1); define('FEEDS_UPDATE_EXISTING', 2); +// Options for handling content in Drupal but not in source data. +define('FEEDS_SKIP_NON_EXISTENT', 'skip'); +define('FEEDS_DELETE_NON_EXISTENT', 'delete'); // Default limit for creating items on a page load, not respected by all // processors. @@ -176,11 +179,18 @@ abstract class FeedsProcessor extends FeedsPlugin { */ public function process(FeedsSource $source, FeedsParserResult $parser_result) { $state = $source->state(FEEDS_PROCESS); + if (!isset($state->removeList) && $parser_result->items) { + $this->initEntitiesToBeRemoved($source, $state); + } while ($item = $parser_result->shiftItem()) { // Check if this item already exists. $entity_id = $this->existingEntityId($source, $parser_result); + // If it's included in the feed, it must not be removed on clean. + if ($entity_id) { + unset($state->removeList[$entity_id]); + } $skip_existing = $this->config['update_existing'] == FEEDS_SKIP_EXISTING; module_invoke_all('feeds_before_update', $source, $item, $entity_id); @@ -264,6 +274,9 @@ abstract class FeedsProcessor extends FeedsPlugin { if ($source->progressImporting() != FEEDS_BATCH_COMPLETE) { return; } + // Remove not included items if needed. + // What actually happens to removed items depends on clean function. + $this->clean($state); $info = $this->entityInfo(); $tokens = array( '@entity' => strtolower($info['label']), @@ -290,6 +303,16 @@ abstract class FeedsProcessor extends FeedsPlugin { ), ); } + if ($state->deleted) { + $messages[] = array( + 'message' => format_plural( + $state->deleted, + 'Removed @number @entity.', + 'Removed @number @entities.', + array('@number' => $state->deleted) + $tokens + ), + ); + } if ($state->failed) { $messages[] = array( 'message' => format_plural( @@ -313,6 +336,59 @@ abstract class FeedsProcessor extends FeedsPlugin { } /** + * Initialize the array of entities to remove with all existing entities + * previously imported from the source. + * + * @param FeedsSource $source + * Source information about this import. + * @param FeedsState $state + */ + protected function initEntitiesToBeRemoved(FeedsSource $source, FeedsState $state) { + $state->removeList = array(); + // We fill it only if needed. + if (!isset($this->config['update_non_existent']) || $this->config['update_non_existent'] == FEEDS_SKIP_NON_EXISTENT) { + return; + } + // Build base select statement. + $info = $this->entityInfo(); + $select = db_select($info['base table'], 'e'); + $select->addField('e', $info['entity keys']['id'], 'entity_id'); + $select->join( + 'feeds_item', + 'fi', + "e.{$info['entity keys']['id']} = fi.entity_id AND fi.entity_type = '{$this->entityType()}'"); + $select->condition('fi.id', $this->id); + $select->condition('fi.feed_nid', $source->feed_nid); + $entities = $select->execute(); + // If not found on process, existing entities will be deleted. + foreach ($entities as $entity) { + // Obviously, items which are still included in the source feed will be + // removed from this array when processed. + $state->removeList[$entity->entity_id] = $entity->entity_id; + } + } + + /** + * Deletes entities which were not found on process. + * + * @todo batch delete? + * + * @param FeedsState $state + */ + protected function clean(FeedsState $state) { + // We clean only if needed. + if (!isset($this->config['update_non_existent']) || $this->config['update_non_existent'] == FEEDS_SKIP_NON_EXISTENT) { + return; + } + + $total = count($state->removeList); + if ($total) { + $this->entityDeleteMultiple($state->removeList); + $state->deleted += $total; + } + } + + /** * Remove all stored results or stored results up to a certain time for a * source. * @@ -609,6 +685,7 @@ abstract class FeedsProcessor extends FeedsPlugin { 'input_format' => NULL, 'skip_hash_check' => FALSE, 'bundle' => $bundle, + 'update_non_existent' => FEEDS_SKIP_NON_EXISTENT, ); } @@ -669,6 +746,17 @@ abstract class FeedsProcessor extends FeedsPlugin { '#required' => TRUE, ); + $form['update_non_existent'] = array( + '#type' => 'radios', + '#title' => t('Action to take when previously imported entities are missing in the feed'), + '#description' => t('Select how entities previously imported and now missing in the feed should be updated.'), + '#options' => array( + FEEDS_SKIP_NON_EXISTENT => t('Skip non-existent entities'), + FEEDS_DELETE_NON_EXISTENT => t('Delete non-existent entities'), + ), + '#default_value' => $this->config['update_non_existent'], + ); + return $form; } diff --git a/tests/feeds/developmentseed_missing.rss2 b/tests/feeds/developmentseed_missing.rss2 new file mode 100644 index 0000000..7e11f08 --- /dev/null +++ b/tests/feeds/developmentseed_missing.rss2 @@ -0,0 +1,263 @@ + + + Development Seed - Technological Solutions for Progressive Organizations + http://developmentseed.org/blog/all + + en + + Managing News Translation Workflow: Two Way Translation Updates + http://developmentseed.org/blog/2009/oct/06/open-atrium-translation-workflow-two-way-updating + <div class="field field-type-text field-field-subtitle"> + <div class="field-items"> + <div class="field-item odd"> + <p>A new translation process for Open Atrium and integration with Localize Drupal</p> </div> + </div> +</div> +<div class='node-body'><p>The <a href="http://openatrium.com/">Open Atrium</a> <a href="http://developmentseed.org/blog/2009/jul/16/open-atrium-solving-translation-puzzle">translation infrastructure</a> (and Drupal translations in general) are progressing quickly. For Open Atrium to be well translated we first need Drupal's modules to be translated, so I am splitting efforts at the moment between helping with <a href="http://localize.drupal.org">Localize Drupal</a> and improving <a href="https://translate.openatrium.com">Open Atrium Translate</a>. Already, it is much easier to automatically download your language, get updates from a translation server, protect locally translated strings, and scale the translation system so that translation servers can talk to each other.</p> + +<h1>Automatically download your language</h1> + +<p><img src="http://farm3.static.flickr.com/2496/3984689117_57559c74eb.jpg" alt="Magical translation install" /></p> + +<p>For more than a month now you have been able to install Open Atrium, select one of its 20+ languages, and have the translation automatically downloaded and installed on your site. While this has been working for awhile now, we are still refining the process. One change we've already made is that now translations are downloaded in multiple smaller packages, rather than a single large one.</p> + +<p>Once your translation is installed, you can use tools like the <a href="http://drupal.org/project/l10n_client">Localization client</a>, which comes bundled in the Open Atrium install, to translate page strings and then optionally contribute them back to the localization server, automatically. This flow of translations goes both ways, so your site gets the latest updates from the server just as you can send your latest updates to the server.</p> + +<h1>Two way translation updates</h1> + +<p><em>But what happens with my locally translated strings, which I like more than the ones that come out of the box, when I update from the server?</em></p> + +<p><img src="http://farm3.static.flickr.com/2442/3984689343_e9b7c32718.jpg" alt="Two ways translation updates" /></p> + +<p>In a word, nothing. There has been a major improvement on this front. Now your translations are tracked and won't be overwritten by someone else's translations when you update, unless you choose for them to be. This means that you can contribute your translations, benefit from others contributing theirs, and make the world a better (translated) place, without loosing any custom work that you want. Let the translations flow!</p></div> + http://developmentseed.org/blog/2009/oct/06/open-atrium-translation-workflow-two-way-updating#comments + Drupal + localization + localization client + localization server + open atrium + translation + translation server + Drupal planet + Tue, 06 Oct 2009 15:21:48 +0000 + Development Seed + 974 at http://developmentseed.org + + + Week in DC Tech: October 5th Edition + http://developmentseed.org/blog/2009/oct/05/week-dc-tech-october-5th-edition + <div class="field field-type-text field-field-subtitle"> + <div class="field-items"> + <div class="field-item odd"> + <p>Drupal, PHP, and Mapping This Week in Washington, DC</p> </div> + </div> +</div> +<div class='node-body'><p><img src="http://developmentseed.org/sites/developmentseed.org/files/dctech2_0_0.png" alt="Week in DC Tech" /></p> + +<p>There are some great technology events happening this week in Washington, DC, so if you're looking to talk code, help map the city, or just hear about some neat projects and ideas, you're in luck. Below are the events that caught our eye, and you can find a full list of technology events happening this week at <a href="http://www.dctechevents.com/">DC Tech Events</a>. Have a great week!</p> + +<h1>Wednesday, October 7</h1> + +<p>6:30 pm</p> + +<p><a href="http://drupal.meetup.com/21/calendar/11332695/"><strong>NOVA Drupal Meetup</strong></a>: Are you a Drupal developer, use a Drupal site, or just want to learn more about the open source content management system? Come out for this meetup to meet other Drupal fans and hear how people are using the CMS.</p> + +<p>6:30 pm</p> + +<p><a href="http://groups.google.com/group/washington-dcphp-group/browse_thread/thread/716d4a625287fef5?hl=en"><strong>DC PHP Beverage Subgroup</strong></a>: If you're looking to talk code with PHP developers who share your interest, come out for this casual meetup to chat over beers.</p> + +<p>7:00 pm</p> + +<p><a href="http://hacdc.org/"><strong>Mapping DC Meeting</strong></a>: Come out for this meetup if you want to help create high quality, free maps of Washington, DC. The <a href="http://wiki.openstreetmap.org/wiki/MappingDC">Mapping DC</a> group is doing this, starting with creating a detailed map of the National Zoo.</p></div> + http://developmentseed.org/blog/2009/oct/05/week-dc-tech-october-5th-edition#comments + Washington DC + Mon, 05 Oct 2009 15:27:40 +0000 + Development Seed + 973 at http://developmentseed.org + + + Mapping Innovation at the World Bank with Open Atrium + http://developmentseed.org/blog/2009/oct/02/mapping-innovation-world-bank-open-atrium + <div class="field field-type-text field-field-subtitle"> + <div class="field-items"> + <div class="field-item odd"> + <p>Using map and faceted search features to improve collaboration</p> </div> + </div> +</div> +<div class='node-body'><p><a href="http://openatrium.com/">Open Atrium</a> is being used as a base platform for collaboration at the World Bank because of its feature flexibility. Last week the World Bank launched a new Open Atrium site called "Innovate," which is being used to support an organization-wide initiative to better share information about successful projects and approaches to solving problems.</p> + +<p>The core of the site is built around helping World Bank staff discover relevant "innovations" happening around the world and providing a space to discuss them with colleagues in topical discussion groups. To facilitate this workflow we built a custom map-based browser feature that combines custom maps with faceted search, letting users quickly find interesting content. The screenshots below from a staging site with a partial database show what this feature looks like.</p> + +<p><img src="http://farm4.static.flickr.com/3419/3974644312_c992e1afe8.jpg" alt="The map-based browser feature makes custom maps with faceted search" /></p> + +<p>As users apply new facets to their searches, the map results update to reveal global coverage for innovations that meet the search criteria.</p> + +<p><img src="http://farm3.static.flickr.com/2600/3974644162_a44cc3a89a.jpg" alt="Add new facets to the search to further customize the map" /></p></div> + http://developmentseed.org/blog/2009/oct/02/mapping-innovation-world-bank-open-atrium#comments + custom mapping + Drupal + faceted search + intranet + map-basec browser + mapbox + open atrium + World Bank + Drupal planet + Fri, 02 Oct 2009 14:31:04 +0000 + Development Seed + 972 at http://developmentseed.org + + + September GeoDC Meetup Tonight + http://developmentseed.org/blog/2009/sep/30/september-geodc-meetup-tonight + <div class="field field-type-text field-field-subtitle"> + <div class="field-items"> + <div class="field-item odd"> + <p>Presentations on Using Amazon&#8217;s Web Services and OpenStreet Map and an iPhone App that Maps Government Data</p> </div> + </div> +</div> +<div class='node-body'><p>Today is the last Wednesday of the month, which means it's time for another <a href="http://geo-dc.ning.com/xn/detail/3537548:Event:1223?xg_source=activity">GeoDC meetup</a>.</p> + +<p><img src="http://farm4.static.flickr.com/3525/3966592859_f7f4cb179c.jpg" alt="September GeoDC Meetup" /></p> + +<p>There will be two short presentations at the meetup. <a href="http://developmentseed.org/team/tom-macwright">Tom MacWright</a> from Development Seed will talk about how using Amazon's web services and <a href="http://www.openstreetmap.org/">OpenStreetMap</a> has helped our mapping team design, render, and host custom maps. Brian Sobel of <a href="http://www.innovationgeo.com/">Innovation Geo</a> will present <a href="http://areyousafedc.com/">Are You Safe</a>, an iPhone App that uses open government data to give users up-to-date and hyper-local information about crime.</p> + +<p>The meetup will run from 7:00 to 9:00 pm at the offices of <a href="http://www.fortiusone.com">Fortius One</a> at 2200 Wilson Blvd, Suite 307 in Arlington, just a <a href="http://maps.google.com/maps?f=q&amp;source=s_q&amp;hl=en&amp;geocode=&amp;q=2200+Wilson+Blvd+%23+307+Arlington,+VA+22201-3324&amp;sll=38.893037,-77.072783&amp;sspn=0.039481,0.087633&amp;ie=UTF8&amp;ll=38.8912,-77.086236&amp;spn=0.009871,0.021908&amp;t=h&amp;z=16&amp;iwloc=A">short walk from the Courthouse metro stop on the orange line</a>. Hope to see you there!</p></div> + http://developmentseed.org/blog/2009/sep/30/september-geodc-meetup-tonight#comments + GeoDC + Washington DC + Wed, 30 Sep 2009 12:02:53 +0000 + Development Seed + 971 at http://developmentseed.org + + + Week in DC Tech: September 28th Edition + http://developmentseed.org/blog/2009/sep/28/week-dc-tech-september-28th-edition + <div class="field field-type-text field-field-subtitle"> + <div class="field-items"> + <div class="field-item odd"> + <p>Healthcare 2.0, iPhone Development, Online Storytelling, and More This Week in Washington, DC</p> </div> + </div> +</div> +<div class='node-body'><p><img src="http://developmentseed.org/sites/developmentseed.org/files/dctech2_0_0.png" alt="Week in DC Tech" /></p> + +<p>Looking to geek out this week? There are a bunch of interesting technology events happening in Washington, DC this week, including a look at how social media is impacting healthcare, a screening of online clips from a journalist/filmmaker, and lightning talks on all kinds of geekery by the HacDC folks. Below are the events that caught our eye, and you can find a full list of what's happening this week in technology over at <a href="http://www.dctechevents.com/">DC Tech Events</a>. Have a great week!</p> + +<h1>Tuesday, September 29</h1> + +<p>6:00 pm</p> + +<p><a href="http://www.meetup.com/DC-MD-VA-Health-2-0/calendar/11291017/"><strong>Health 2.0 Meetup</strong></a>: Curious as to how - and if - online technologies are impacting healthcare? At this meetup two speakers - Sanjay Koyani from the U.S. Food and Drug Administration and Taylor Walsh from MetroHealth Media - will talk about what they're seeing and implementing.</p> + +<p>7:00 pm</p> + +<p><a href="http://nscodernightdc.com/"><strong>NSCoderNightDC</strong></a>: Want to build an iphone app, or talk about one that you've already built? Come out for this meetup to talk about mac and iphone development, share the latest news from Apple, and eat some delicious French desserts.</p></div> + http://developmentseed.org/blog/2009/sep/28/week-dc-tech-september-28th-edition#comments + Washington DC + Mon, 28 Sep 2009 15:33:15 +0000 + Development Seed + 970 at http://developmentseed.org + + + Open Data for Microfinance: The New MIXMarket.org + http://developmentseed.org/blog/2009/sep/24/open-data-microfinance-new-mixmarketorg + <div class="field field-type-text field-field-subtitle"> + <div class="field-items"> + <div class="field-item odd"> + <p>Relaunch focuses on rich data visualization and downloadable data</p> </div> + </div> +</div> +<div class='node-body'><p>The launch of the new <a href="http://www.mixmarket.org/">MIX Market</a> is a big win for open data in international development, and it vastly improves how rich financial data sets can be accessed. The MIX Market is like a Bloomberg for microfinance, publishing data on more than 1,500 microfinance institutions (MFIs) in more than 190 countries and affecting 80,021,351 people. Additionally, each MFI has as many as 150 financial indicators and in some cases going back as far as 1995. The goal of this tool is simple - to open this information up to help MFIs, researchers, raters, evaluators, and governmental and regulatory agencies better see the marketplace, and that makes for better international development.</p> + +<p>There are profiles for every country that the MIX Market is hosting. Take a look at the country landing page for India, showing how India stacks up to other peer groups and listing out all MFIs, networks, and funders and service providers.</p> + +<p><img src="http://farm4.static.flickr.com/3517/3941870722_390f5aa65d.jpg" alt="Country profiles give a quick overview of the performance of its microfinance institutions." /></p></div> + http://developmentseed.org/blog/2009/sep/24/open-data-microfinance-new-mixmarketorg#comments + data visualization + graphs + microfinance + MIX Market + open data + salesforce + Drupal planet + Thu, 24 Sep 2009 13:09:10 +0000 + Development Seed + 969 at http://developmentseed.org + + + Integrating the Siteminder Access System in an Open Atrium-based Intranet + http://developmentseed.org/blog/2009/sep/22/integrating-siteminder-access-system-open-atrium-based-intranet + <div class="field field-type-text field-field-subtitle"> + <div class="field-items"> + <div class="field-item odd"> + <p>Upgraded Siteminder Module in Drupal allows for better integration with Siteminder </p> </div> + </div> +</div> +<div class='node-body'><p>In <a href="http://developmentseed.org/blog/2009/sep/08/custom-open-atrium-intranet-launches-world-bank">our recent work on the World Bank's Communicate intranet</a>, we needed to integrate the <a href="http://www.ca.com/us/internet-access-control.aspx">Siteminder access system</a> into the <a href="http://openatrium.com/">Open Atrium</a>-based intranet "Communicate" to allow World Bank staff to use the same single sign-on credentials that they use to access all their internal web systems. To do this, we upgraded the Siteminder module for Drupal. You can download the <a href="http://drupal.org/project/siteminder">new module from its Drupal project page</a> and <a href="http://cvs.drupal.org/viewvc.py/drupal/contributions/modules/siteminder/README.txt?revision=1.2&amp;view=markup&amp;pathrev=DRUPAL-6--1-0-ALPHA1">learn more about its API and how to write your own Siteminder plugin in its documentation</a> and from reading the module's code. First, here is a little more background on the changes.</p> + +<p>The Siteminder system, from <a href="http://www.ca.com/us/">Computer Associates</a>, is used by many enterprise-level organizations to authenticate signing on to their web resources. How it works is that you can designate a site - like an Open Atrium powered intranet - to be protected by the Siteminder system. Once a site is protected by Siteminder, all traffic to that site is routed through Siteminder first and then on to the actual site. Siteminder sets certain HTTP headers in the user's request, and Drupal can then examine them to determine credentials. What the Drupal Siteminder module does is map the Siteminder header values to Drupal users and allow a user to login based on the headers they send.</p> + +<p>In addition to authentication, the Siteminder system also stores other information about users. When the Siteminder system sends HTTP headers for authentication, it can also send information about a user - like her name, email address, phone number, and so on. We wanted to be able to pull this information into the intranet too. To achieve this, we re-wrote the Siteminder module in such a way that it's easy to write a plugin module to provide the fields to which you'd like to map this extra Siteminder meta information and to determine how this information is processed and saved. To do this for the World Bank's intranet, we built the Siteminder Profile module, which lets you pick a CCK node type to serve as the target content profile for a user as well as select a few taxonomy vocabularies. Then by using the main module's administrative interface, you can choose which Siteminder headers should get mapped to which CCK fields and vocabularies based on the designated node type and vocabularies you selected in the Siteminder Profile settings page.</p> + +<p>But what happens if a person's information changes in the Siteminder database - for example if they change phone numbers or office buildings? The Siteminder module now has built-in capability and an API to check whether values in users' profiles have changed in the Siteminder system. The Siteminder Profile module uses this API and saves a new version of a user's profile if it detects that a value has changed in the Siteminder system database.</p></div> + http://developmentseed.org/blog/2009/sep/22/integrating-siteminder-access-system-open-atrium-based-intranet#comments + authentication + Drupal + open atrium + siteminder + siteminder module + Drupal planet + Tue, 22 Sep 2009 18:02:21 +0000 + Development Seed + 964 at http://developmentseed.org + + + Week in DC Tech: September 21 Edition + http://developmentseed.org/blog/2009/sep/21/week-dc-tech-september-21-edition + <div class="field field-type-text field-field-subtitle"> + <div class="field-items"> + <div class="field-item odd"> + <p>PHP, Design, Twitter, and Wikipedia This Week in Washington, DC</p> </div> + </div> +</div> +<div class='node-body'><p><img src="http://developmentseed.org/sites/default/files/dctech2_0.png" alt="Week in DC Tech" /></p> + +<p>There's an interesting variety of technology events happening in Washington, DC this week with focuses ranging from using Twitter for advocacy to drinking beers with php developers to discussing designing way outside of the box. Additionally tomorrow is international Car Free Day and there are events happening throughout the city to celebrate it and help you how to rely on cars less. Below are the events that caught our eye, and you can find a full list of the week's technology events at <a href="http://www.dctechevents.com/">DC Tech Events</a>.</p> + +<h2>Tuesday, September 22</h2> + +<p>All day</p> + +<p><a href="http://www.carfreemetrodc.com/"><strong>Car Free Day</strong></a>: Help reduce traffic and improve air quality by leaving your car at home on Tuesday in celebration of Car Free Day. There are also <a href="http://www.carfreemetrodc.com/Information/tabid/57/Default.aspx">free bike repair trainings, yoga classes, and other events</a> happening throughout the day to help you lead a car free lifestyle.</p> + +<p>6:00 - 8:00 pm</p> + +<p><a href="http://www.php.net/cal.php?id=3075"><strong>DC PHP Beverage Subgroup</strong></a>: Come out to talk code with other php developers over a few beers. This is a great opportunity to get to know local php developers in a casual setting while sharing stories about your code.</p></div> + http://developmentseed.org/blog/2009/sep/21/week-dc-tech-september-21-edition#comments + Washington DC + Mon, 21 Sep 2009 16:03:24 +0000 + Development Seed + 968 at http://developmentseed.org + + + Peru's Software Freedom Day: Impressions and Photos + http://developmentseed.org/blog/2009/sep/21/perus-software-freedom-day-impressions-and-photos + <div class='node-body'><p>There was a great turn out a <a href="http://www.sfdperu.org/">Software Freedom Day</a> this weekend with 400 people in attendance and a solid 30 presentations. The <a href="http://developmentseed.org/blog/2009/sep/15/preparing-perus-software-freedom-day-talks-drupal-features-and-open-atrium">presentations in the Drupal track</a> were some of the best attended sessions of the day. To get a sense of Drupal's traction down here, "Drupal" was mentioned in many sessions and conversations throughout the day, and not just by the people working directly with Drupal.</p> + +<p><img src="http://farm3.static.flickr.com/2653/3940335249_57ce995a84.jpg" alt="Presenting on Features in Drupal and Managing News" /> +<em>Presenting on Features in Drupal and Managing News</em></p> + +<p>I had a great time meeting people and learning about the work being done in the different open source communities here in Peru. Software Freedom Day is becoming an annual event in Peru, and there were many discussions on improving the event for next year as well as keeping the energy going to improve the image of open source software in the country. It's great to see the community looking forward like this, and I'm excited to help keep the open source movement growing in Peru.</p> + +<p><a href="http://www.flickr.com/photos/developmentseed/sets/72157622423999830/">More photos from the event here.</a></p></div> + http://developmentseed.org/blog/2009/sep/21/perus-software-freedom-day-impressions-and-photos#comments + Drupal + open source + Peru + software freedom day + Mon, 21 Sep 2009 14:22:35 +0000 + Development Seed + 967 at http://developmentseed.org + + + diff --git a/tests/feeds_processor_node.test b/tests/feeds_processor_node.test index e5d4ecd..e4e37ea 100644 --- a/tests/feeds_processor_node.test +++ b/tests/feeds_processor_node.test @@ -293,6 +293,34 @@ class FeedsRSStoNodesTest extends FeedsWebTestCase { $this->assertText('Created 10 nodes'); $this->assertFeedItemCount(10); + // Enable unpublish missing nodes and import updated feed file. + $this->setSettings('syndication_standalone', 'FeedsNodeProcessor', array('update_non_existent' => 'unpublish')); + $missing_url = $GLOBALS['base_url'] . '/' . drupal_get_path('module', 'feeds') . '/tests/feeds/developmentseed_missing.rss2'; + $this->importURL('syndication_standalone', $missing_url); + $this->assertText('Updated 1 node'); + $this->assertFeedItemCount(10); + + // Now delete all items. + $this->drupalPost('import/syndication_standalone/delete-items', array(), 'Delete'); + $this->assertText('Deleted 10 nodes'); + $this->assertFeedItemCount(0); + + // Import again, to reset node counts + $this->importURL('syndication_standalone', $feed_url); + $this->assertText('Created 10 nodes'); + $this->assertFeedItemCount(10); + + // Change settings to delete non existent nodes from feed. + $this->setSettings('syndication_standalone', 'FeedsNodeProcessor', array('update_non_existent' => 'delete')); + $this->importURL('syndication_standalone', $missing_url); + $this->assertText('Removed 1 node'); + $this->assertFeedItemCount(9); + + // Now delete all items. + $this->drupalPost('import/syndication_standalone/delete-items', array(), 'Delete'); + $this->assertText('Deleted 9 nodes'); + $this->assertFeedItemCount(0); + // Login with new user with only access content permissions. $this->drupalLogin($this->auth_user);