{"id":1555,"date":"2016-01-28T08:19:01","date_gmt":"2016-01-28T12:19:01","guid":{"rendered":"http:\/\/agileadam.com\/?p=1555"},"modified":"2016-02-02T14:34:26","modified_gmt":"2016-02-02T18:34:26","slug":"auto-create-url-redirects-in-feeds","status":"publish","type":"post","link":"https:\/\/agileadam.com\/2016\/01\/auto-create-url-redirects-in-feeds\/","title":{"rendered":"Auto-create URL Redirects in Feeds"},"content":{"rendered":"

I’m working on a website redesign. The original site used awful URL aliases where nearly everything got a URL like\u00a0\/content\/title-of-page-would-end-up-looking-like-this<\/em>. There are no “sections” to speak of in the URL structure, and there are several thousand nodes! I’m migrating most of the content from the “old” site to the new one using Feeds. Rather than manually mess with rewrite rules, I figured I should just create a redirect at the time of migration. We typically handle redirects\/rewrites\u00a0using the redirect\u00a0module<\/a>. So, how do you do this?<\/p>\n

The first step is to capture the old URL. In my CSV export View on the old site, I simply included the URL alias (Content: Path<\/em> in views) with a label of twentyfifteen_url_alias<\/em>. We’re launching this new site in 2016, so I’m calling anything old-site-related twentyfifteen<\/em>.<\/p>\n

Now we have to make use of this new column in the CSV. It’s easy enough to call in the new source field, but what do we assign it to (what is the\u00a0target<\/em> in Feeds-speak)?\"Screenshot_2016-01-28_07-07-06\"<\/a><\/p>\n

This is where we have to do some coding.\u00a0We need to store our twentyfifteen_url_alias\u00a0<\/em>value somewhere, and it’d be best to do so temporarily. There’s no reason to hold onto this value after we create the redirect.<\/p>\n

To do this, we need to setup a new target. We use hook_feeds_processor_targets_alter()<\/a> for this.<\/p>\n

Here’s what that looks like in my\u00a0twentyfifteen_importers<\/em>\u00a0custom module:<\/p>\n

\/**\r\n * Implements hook_feeds_processor_targets_alter().\r\n *\/\r\nfunction twentyfifteen_importers_feeds_processor_targets_alter(&$targets, $type, $bundle) {\r\n  if ($type == 'node') {\r\n    $targets['twentyfifteen_url_alias'] = array(\r\n      'name' => t('Twentyfifteen URL for redirect'),\r\n      'description' => t('If populated, this URL will automatically redirect to the new imported node'),\r\n      'callback' => 'twentyfifteen_importers_feeds_twentyfifteen_url_alias_set_target',\r\n    );\r\n  }\r\n}<\/pre>\n

Notice there is a callback function. We need to create that function:<\/p>\n

\/**\r\n * Mapping callback for the \"Twentyfifteen URL for redirect\" target\r\n *\/\r\nfunction twentyfifteen_importers_feeds_twentyfifteen_url_alias_set_target($source, $entity, $target, $value, $mapping) {\r\n  if (!empty($value[0])) {\r\n    \/\/ If path starts with a forward-slash, strip it off\r\n    $entity->twentyfifteen_url_alias = ltrim($value[0], '\/');\r\n  }\r\n}<\/pre>\n

At this point we should be able to refresh the feeds “Mapping” screen to see the new target. You might be wondering, though, whether or not this will do anything at this point. \"Screenshot_2016-01-28_07-13-03\"The answer is no, it won’t do anything more than add the value temporarily to the entity that’s being processed. Of course, we want to make a new URL redirect out of this value. To do this we implement the\u00a0hook_node_insert()<\/a> hook (because this hook will execute after the node object gets a proper node ID).<\/p>\n

\/**\r\n * Implements hook_node_insert().\r\n *\/\r\nfunction twentyfifteen_importers_node_insert($node) {\r\n  \/\/ Adapted from https:\/\/www.drupal.org\/node\/1279618#comment-10736364\r\n  if (isset($node->twentyfifteen_url_alias)) {\r\n    $query = db_select('redirect', 'r');\r\n    $query->fields('r', array('source'));\r\n    $redirect_sources = $query->execute()->fetchCol();\r\n\r\n    if (isset($node->nid) && (!in_array($node->twentyfifteen_url_alias, $redirect_sources))){\r\n      $redirect = new stdClass();\r\n\r\n      module_invoke('redirect', 'object_prepare', $redirect,\r\n        array(\r\n          'source' => $node->twentyfifteen_url_alias,\r\n          'source_options' => array(),\r\n          'redirect' => 'node\/' . $node->nid,\r\n          'redirect_options' => array(),\r\n          'language' => LANGUAGE_NONE,\r\n        )\r\n      );\r\n\r\n      module_invoke('redirect', 'save', $redirect);\r\n    }\r\n  }\r\n}<\/pre>\n

That’s all there is to it! As feeds processes each entity it will look for a\u00a0twentyfifteen_url_alias<\/em> property and will create a new redirect (in\u00a0the Redirect module) if the redirect does not exist yet.<\/p>\n","protected":false},"excerpt":{"rendered":"

I’m working on a website redesign. The original site used awful URL aliases where nearly everything got a URL like\u00a0\/content\/title-of-page-would-end-up-looking-like-this. There are no “sections” to speak of in the URL structure, and there are several thousand nodes! I’m migrating most of the content from the “old” site to the new one using Feeds. Rather than manually mess with rewrite rules, I figured I should just create a redirect at the time of migration. We typically handle redirects\/rewrites\u00a0using the redirect\u00a0module. So, how do you do this?<\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":[],"categories":[79],"tags":[83,273,272,274],"_links":{"self":[{"href":"https:\/\/agileadam.com\/wp-json\/wp\/v2\/posts\/1555"}],"collection":[{"href":"https:\/\/agileadam.com\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/agileadam.com\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/agileadam.com\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/agileadam.com\/wp-json\/wp\/v2\/comments?post=1555"}],"version-history":[{"count":8,"href":"https:\/\/agileadam.com\/wp-json\/wp\/v2\/posts\/1555\/revisions"}],"predecessor-version":[{"id":1565,"href":"https:\/\/agileadam.com\/wp-json\/wp\/v2\/posts\/1555\/revisions\/1565"}],"wp:attachment":[{"href":"https:\/\/agileadam.com\/wp-json\/wp\/v2\/media?parent=1555"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/agileadam.com\/wp-json\/wp\/v2\/categories?post=1555"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/agileadam.com\/wp-json\/wp\/v2\/tags?post=1555"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}