Get url path of node using entity query - drupal

I'm trying to figure out how I can get the path of a node via entity query. So far I've managed to fetch the title of the node but I can seem to find a solution on how to get the node path/url. Here is a sample of my code
$facultyPostings = $query->get('node')
->condition('status', 1, '=')
->condition('type', 'careers')
->condition('field_career_directory', 'Faculty Postings', '=')
->sort('created')
->execute();
foreach ($facultyPostings as $key => $faculty_postings_careers) {
$careersNode = _nodeLoad($faculty_postings_careers);
$variables['faculty_postings'][$key]['title'] = $careersNode->get('title')->value;
$variables['faculty_postings'][$key]['path'] = $careersNode->get('path')->value;
}

You need to use the service provided in Drupal 8 core.services.yml file. So in your loop you can use.
//think so this will get the nid
$nid = $careersNode->get('id')->value;
//This one is correct as per the documentation
$alias = \Drupal::service('path.alias_manager')->getAliasByPath('/node/'.$nid);
https://api.drupal.org/api/drupal/core%21lib%21Drupal%21Core%21Path%21AliasManager.php/class/AliasManager/8.3.x

Related

Is it possible to update(overwrite) node id of a page content in drupal 7?

I am doing migration from drupal 6 to drupal 7. However, I migrated all the page contents successfully, I want to keep the same nodeid from my previous version.
The below piece of code did it. But i need to update each and every table. Even though it works, I want to confirm like Is there any function available to do this process. something like node_update ?
Example: After migration i want to update the node id of a page from 123 to 12. So that it should update all the tables where node id 123 has been referred to 12.
Code:
public function postImport() {
$original_node_data = Database::getConnection('default', 'legacy')
->select('node', 'nd')
->fields('nd', array('nid', 'type', 'title'))
->execute()
->fetchAll();
foreach ($original_node_data as $ori_nd_dta) {
$ori_nd_id = $ori_nd_dta->nid;
$oti_nd_title = $ori_nd_dta->title;
$duplicate_node_data = Database::getConnection('default', 'default')
->select('node', 'nd')
->fields('nd', array('nid', 'title'))
->condition('title', $oti_nd_title)
->execute()
->fetchAll();
foreach ($duplicate_node_data as $dup_data) {
$dup_nd_id = $dup_data->nid;
}
$update_node = db_update('node')
->fields(array('nid' => $ori_nd_id))
->condition('nid', $dup_nd_id)
->execute();
$update_node_rev = db_update('node_revision')
->fields(array('nid' => $ori_nd_id))
->condition('nid', $dup_nd_id)
->execute();
.......
.......
}
}
It is possible if the node table is empty.
I think people use UUID for this issue.

Drupal Bulk Update Url Alias

I have a set of nodes (about 200) that need to have their url alias updated since we changed the setup; from "site.com/things-to-do/title" to "site.com/guides/title"
I tried using VBO, but when I select the nodes, click Update Url Alias, and then execute, nothing happens.
Although I'd rather not do a straight DB update, I also tried:
"UPDATE url_alias set dst = replace(dst, 'things-to-do', 'guides') WHERE url_alias LIKE 'things-to-do/%';
Thanks
Path auto should fix your problem:
http://drupal.org/project/pathauto
It will give you the option to delete existing aliases and regenerate them.
Apart from using the pathauto module stated above, you should also use path redirect module - http://drupal.org/project/path_redirect - so that you can redirect your old links to the newly created ones, else your old links will die out.
You can also use Global redirect - http://drupal.org/project/globalredirect
Here's a quick script I wrote that solves the problem. It does a simple find and replace on the alias and then creates a redirect.
You need the url_alias and path_redirect modules installed, this is for Drupal 6. This isn't the cleanest syntax (it was written quickly) but it works.
$string_to_replace = "foo";
$replacement_string = "bar";
//Get an array containing all aliases that need to be updated
$query = "SELECT * from url_alias where dst like '%$string_to_replace%'";
$result = db_query($query);
$paths = array();
while ($row = db_fetch_array($result)){
$paths[] = $row;
}
foreach($paths as $path){
//Determine the new path
$path['new_dst'] = str_replace($string_to_replace,$replacement_string,$path['dst']);
//Update the existing url_alias
$query = "UPDATE url_alias SET dst = '".$path['new_dst']."' WHERE pid = " . $path['pid'];
$result = db_query($query);
//Create and save a redirect
$redirect = array(
'source' => $path['dst'],
'redirect' => $path['src'],
);
path_redirect_save($redirect);
}
$nids = Drupal::entityQuery('node')
->condition('type', 'CONTENT_TYPE')
->execute();
$nodes = Node::loadMultiple($nids);
foreach($nodes as $node) {
$node->path->pathauto = 1;
$node->save();
}
I hope above code will solve the issue.

Drupal taxonomy with special characters in a term

I sync data from external source to my Drupal installation. I have problem when i'm adding taxonomy term relation to my newly created node.
I'm syncing cars and if manufacturer name ($name in code) is not in vocabulary, it will get added to it. If it already exists, tid attached to node.
This works perfectly with terms like Ferrari or Volkswagen. But then there is Mercedes-Bentz. For some reason EntityFieldQuery doesn't seem to find it from vocabulary, because this code, when run in loop, creates Mercedes-Bentz terms over and over again.
I guess the problem is that dash between words. I'd like to see SQL clause behind EntityFieldQuery, but i don't have entire drupal setup up when i'm running this, so modules like Devel are not loaded. And I don't have a clue how to inspect SQL otherwise.
I'm more than grateful of suggestions how to debug or how to solve this. Every link is appreciated.
Here is my code:
$query = new EntityFieldQuery();
$result = $query
->entityCondition('entity_type', 'taxonomy_term')
->propertyCondition('name', $name) // $name = manufacturer, like "Ferrari"
->propertyCondition('vid', 2)
->execute();
if(!empty($result))
{
$tmp = array_pop($result['taxonomy_term']);
$node->field_brand[LANGUAGE_NONE][0]['tid'] = $tmp->tid;
}
else
{
$term = new stdClass();
$term->vid = 2;
$term->name = $name
taxonomy_term_save($term);
$node->field_brand[LANGUAGE_NONE][0]['tid'] = $term->tid;
}
There is a way to do the same with taxonomy_get_term_by_name(), but i guess it is not preferred way and the solution explained in question should be right for this.
I think we are seeing Drupal bug here. But for others trying to do that, here is the solution:
$test = taxonomy_get_term_by_name($name);
// It should be full of unique names, so no need to go through all of them
if(!empty($test))
{
$tmp = array_pop($test);
$node->field_brand[LANGUAGE_NONE][0]['tid'] = $tmp->tid;
}
else
{
$term = new stdClass();
$term->vid = 2;
$term->name = $name;
taxonomy_term_save($term);
$node->field_brand[LANGUAGE_NONE][0]['tid'] = $term->tid;
}

Setting location data programmatically

I'm stuck on a problem that I've researched for several days with no luck and the answers here are usually spot on.
I have custom module code that adds a node from form supplied data:
$edit = array();
$edit['uid'] = $user->id;
$edit['name'] = $user->name;
$edit['status'] = 1;
$edit['taxonomy'] = array($term_id);
$edit['title'] = $Title;
$edit['body'] = $body;
etc...
and then saved with:
node_invoke_nodeapi($edit, $nType);
node_validate($edit);
if ($errors = form_get_errors()) {
print_r($errors);
}
$node = node_submit($edit);
node_save($node);
This all works perfectly. But I'm trying to add location data to each node based on a supplied (sanitized) zip field.
I have gmap and location modules installed and working. When I add the zip directly using the drupal content editor it all works. Even the views gmap. So i know versions and mods are all correct.
I've used this:
$location = array(
'country' => 'US',
'postal_code' => $zip,
);
$locationID = location_save($location);
and this:
$location['country'] = "US";
$location['postal_code'] = $zip;
$locationID = location_save($location);
with and without the country element.
And then in the node data init section (above) this:
$edit->locations[0]['lid'] = $locationID;
or
if($locationID) $edit['field_location'][0]['lid'] = $locationID;
or
if($locationID) $edit['location'][0]['lid'] = $locationID;
But none of this works. The submit will go through ok actually but no location data is saved. And no errors thrown.
Any help with this would be greatly appreciated.
I did get this to work, (in case anyone is having the same issue and stumbles upon this), by creating the node first and then adding the location data to the node with:
$locations = array();
$locations[0]['postal_code'] = $zip;
$criteria = array();
$criteria['nid'] = $node->nid;
$criteria['vid'] = $node->vid;
$criteria['genid'] = 'NAME OF NODE TYPE HERE';
location_save_locations( $locations, $criteria );
I guess location_save_locations is the correct way of doing it, not location_save.
Following your approach, as exposed by the wider location_save_locations() at line 4, you can update a location with location_save($locations[$key], TRUE, $criteria).
A few notes:
location_save return the lid of the saved location, or FALSE if the location is considered "empty."
Clean your cache or query the database ( mysql> SELECT * FROM location ORDER BY lid DESC limit 6 ) for a fresh view of the new entity location (ie: node_load data may be cached).
Alternatively, if you are handling an entity with a location field, you may try something cleaner like:
// Updated the location.
$node->field_location['und'][0] = $location;
// Save the node.
node_save ($node);

Create node programmatically with cck location field

I try to programmatically create a node of custom contenttype "location" in Drupal 6, with the node containing a location field (http://drupal.org/project/location) called "location" (yes I know, the nomenclature could be better, but I am just experimenting on this at the moment).
Creating the node works just fine, but I cannot find a way to set the contents for the location field - i.e. the node is created with all content but the value for then location field.
I try creating the node like this:
$newNode = (object) NULL;
$newNode->type = 'location';
$newNode->title = $locationName;
$newNode->uid = $userId;
$newNode->created = strtotime("now");
$newNode->changed = strtotime("now");
$newNode->status = 1;
$newNode->comment = 0;
$newNode->promote = 0;
$newNode->moderate = 0;
$newNode->sticky = 0;
$newNode->field_location[0]['street'] = 'Teststraße';
$newNode->field_location[0]['postal_code'] = '12345';
$newNode->field_location[0]['city'] = 'Musterstadt';
node_save($newNode);
The node gets created with the correct title, but the location fields remain unset.
How can I programmatically set the location-related fields?
Thanks in advance!
Wanted to add this as a comment, but it seems like putting code into the comment is rather problematic. So here we go: I changed the internas so that I do not use a cck field anymore, but use the default location option as suggested by googletorp.
The actual code to create a new location and assign this to a new node looks like this:
$location['street'] = "myStreet";
$location['postal_code'] = "12345";
...
$newLocationId = location_save($location);
$newNode = ...
$newNode->locations[0]['lid'] = $newLocationId;
node_save($newNode);
Thanks for the guidance :)
Instead of node_save, many people recommend using drupal_execute to programmatically submit the node edit form. This gives you the benefit of form validation.
See http://thedrupalblog.com/programmatically-create-any-node-type-using-drupal-execute for an excellent example of using drupal_execute. Don't forget to look at the comment http://thedrupalblog.com/programmatically-create-any-node-type-using-drupal-execute#comment-70 to see some additional info on CCK fields.
The advantage of drupal_execute is that you get form validation also. So after the drupal_executestatement you can see if there were any errors using form_get_errors ( http://api.drupal.org/api/function/form_get_errors/6 ). See snippet (pasted below) from http://civicactions.com/blog/cck_import_and_update for an example of using form_get_errors
$node->type = 'yourtype';
$values = array();
$values[...] = ...;
drupal_execute('yourtype_node_form', $values, $node);
$errors = form_get_errors();
if (count($errors)) {
// do something ...
}
Another very nice resource on programmatic submission of nodes using drupal_execute can be found at http://drupal.org/node/293663
I have done this, only not with a CCK field but the default location option you can add to nodes.
What I did to make it work, was to first save the location (there's an API function for it) and then add the location id from the saved location.
Sample code:
Note, $center is from an external source, so it's not Drupal related. I know all my locations are from Denmark in my example, so that part is just hardcoded.
When you don't use a CCK field, you don't need to save the location data on the node, instead you can just save the location and pair the location yourself. It's a quick solution, instead of running through the node form like suggested. For complex nodes, that might be the better choice, but when it's simple, this is done faster.
// Update the location data.
$location = is_array($node->location) ? $node->location : array();
$location += array(
'street' => $center->address->address2,
'city' => $center->address->zipName,
'postal_code' => $center->address->zip,
'country' => 'dk',
'country_name' => 'Denmark',
);
location_save($location);
// Insert location instance, if it's not set yet.
$criteria = array(
':nid' => $node->nid,
':vid' => $node->vid,
':lid' => $location['lid'],
);
if (!db_result(db_query("SELECT COUNT(*) FROM {location_instance} WHERE nid = %d AND vid = %d AND lid = %d;", $criteria))) {
db_query("INSERT INTO {location_instance} (nid, vid, lid) VALUES (%d, %d, %d)", $criteria);
}
For Drupal 7, saving as default location tab.
$location = array(
'latitude' => $row->gmapycord,
'longitude' => $row->gmapxcord,
);
$lid = location_save($location);
if ($lid) {
$entity->locations['0']['lid'] = $lid;
}
Inspired from: here

Resources