Recipe for adding Drupal node records - indexing

I am looking for a recipe for adding Drupal node records.
I have identified three tables.
node_revisions
nid=249 - vid + 1?
vid=248 - auto-increment
node:
nid=250 - vid + 1?
vid=249 - auto-increment
content_type_my_content
vid=248 - from node_revisions table?
nid=249 - from node table?
Am I on right track?
Is there some helper functions for this?

If you are looking to programatically create nodes, use the Drupal API.
Start by creating a $node object. Fill in title, type, status, body, plus any CCK fields. At the end, call node_save($node);.
node_save will save your node object and do the necessary database work.
Check this out:
http://api.drupal.org/api/function/node_save/6
http://mediumexposure.com/how-build-node-drupal-programmatically/
The easiest way to see what each type of content type has as fields is to create a node (for example, Page), then use var_dump() to see the node's contents. That will show you every field you will need to use in your node object creation script.
Some folks will say you should create a form array, and call drupal_execute() on it so validation is performed before it's saved to the database. Either way is fine.

Kevin - With your help I have made good progress.
Node and CCK fields are now being populated.
Location (long/lat) is populated but not showing up on View screen.
Checkboxes are not being populated.
global $user;
$newnode = new stdClass();
$newnode->title = 'New node title';
$newnode->body = "this is a new node, created by import function";
$newnode->uid = $user->uid;
$newnode->type = 'items';
$newnode->status = 1;
$newnode->promote = 0;
// CCK fields
$newnode->field_myfield1[0]['value'] = 'test 1';
$newnode->field_myfield2[0]['value'] = 'test 2';
$newnode->field_mycheckbox[0]['value'] = 1;
// longitude, lalitude
// $newnode->locations[0]['lid'] = ?;
$newnode->locations[0]['street'] = 'xx';
$newnode->locations[0]['city'] = 'xx';
$newnode->locations[0]['province'] = 'xx';
$newnode->locations[0]['postal_code'] = 'xx';
$newnode->locations[0]['latitude'] = 0;
$newnode->locations[0]['longitude'] = 0;
$newnode = node_submit($newnode);
node_save($newnode);
content_insert($newnode);

OK. here is the full recipe. Drupal does the rest automagically.
global $user;
// Node fields
$newnode = new stdClass();
$newnode->title = $data[0];
$newnode->body = $data[1];
$newnode->uid = $user->uid;
$newnode->type = 'mytype';
$newnode->status = 1;
$newnode->promote = 0;
// CCK fields
$newnode->field_myfield1[0]['value'] = $something;
$newnode->field_myfield2[0]['value'] = $something;
$newnode->field_my_checkbox[0]['value'] = $something;
// longitude, latitude
$newnode->field_loc_latitude[0]['street'] = $something;
$newnode->field_loc_latitude[0]['city'] = $something;
$newnode->field_loc_latitude[0]['province'] = $something;
$newnode->field_loc_latitude[0]['postal_code'] = $something;
$newnode->field_loc_latitude[0]['latitude'] = '';
$newnode->field_loc_latitude[0]['longitude'] = '';
$newnode = node_submit($newnode);
node_save($newnode);
content_insert($newnode);

Related

Updating Handles for MatrixBlock "Field Layout Fields" in Craft CMS Migrations

After reading this excellent Medium article, I've been stoked on Migrations in CraftCMS. They've been super useful in importing the same changes across the 10 or so developers who work on our site.
When trying to change the handles on individual fields within block types within matrix blocks (whew) via migrations, I came across a hurdle. The field itself can easily have its "handle" attribute updated, but the columns table for that matrix block's content (matrixcontent_xxxxx) do not get updated to reflect any updated handles. The association between the Matrix Block & its associated Matrix Content table only exists in the info column in the field record for that Matrix Block.
If the Matrix Block's field is updated via the CMS, the change is reflected, so it's gotta be somewhere in Craft's source, but it's not apparent through the Craft CMS Class Reference.
Any ideas?
Edited to add the migration snippet:
public function safeUp()
{
// Strings for labels, etc.
$matrix_block_instructions = "instructions";
$block_label = "Video";
$block_handle = "video";
$field_handle = "video_url";
$field_label = "Video URL";
$field_instructions = "Add a YouTube or Facebook video URL.";
// Fetching the MatrixBlock fields used on the entries themselves
$video_gallery_1 = Craft::$app->fields->getFieldByHandle("handle_1");
$video_gallery_2 = Craft::$app->fields->getFieldByHandle("handle_2");
$video_gallery_3 = Craft::$app->fields->getFieldByHandle("handle_3");
$galleries = [$video_gallery_1, $video_gallery_2, $video_gallery_3];
foreach( $galleries as $gallery ) {
// Fetching the record for this specific MatrixBlock field.
$gallery_record = \craft\records\Field::find()->where(
['id' => $gallery->id]
)->one();
// Fetching the record for this specific MatrixBlockType
$gallery_block_id = $gallery->getBlockTypes()[0]->id;
$gallery_block = \craft\records\MatrixBlockType::find()->where(
['id' => $gallery_block_id]
)->one();
// Assigning standard labels for the MatrixBlockType
$gallery_block->name = $block_label;
$gallery_block->handle = $block_handle;
$gallery_block->update();
// Getting the specific ... 1 ... field to edit
$field_group = \craft\records\FieldLayout::find()->where(
['id' => $gallery_block->fieldLayoutId]
)->one();
$field_layout_field = $field_group->fields[0];
$field = $field_layout_field->field;
$field = \craft\records\Field::find()->where(
['id' => $field->id]
)->one();
// Assigning standard labels for the Label
$field->name = $field_label;
$field->handle = $field_handle;
$field->instructions = $field_instructions;
$field->update();
// Updating the MatrixBlock record with new instructions
$gallery_record->refresh();
$gallery_record->instructions = $matrix_block_instructions;
$gallery_record->update();
}
OK, so my apologies if anyone was stoked on figuring this out, but my approach above was kind of a crazy person's approach, but I've found my own solution.
The key here is that I should have been interacting with craft\fields\MatrixBlock and the craft\fields\PlainText objects, not craft\records\Field objects. There's a method within \craft\services\Fields for saving the field that requires a FieldInterface implemented. This is actually the default classes returned, and I was making more work for myself in the code!
Within that foreach loop, this worked out:
// Fetching the record for this specific MatrixBlock field.
$gallery->instructions = $matrix_block_instructions;
// Update the MatrixBlockType
$gallery_block_id = $gallery->getBlockTypes()[0]->id;
$gallery_block = \craft\records\MatrixBlockType::find()->where(
['id' => $gallery_block_id]
)->one();
$gallery_block->name = $block_label;
$gallery_block->handle = $block_handle;
$gallery_block->update();
// Update the actual field.
$field = $gallery->blockTypeFields[0];
$field->name = $field_label;
$field->handle = $field_handle;
$field->instructions = $field_instructions;
Craft::$app->getFields()->saveField( $field );
Craft::$app->getFields()->saveField( $gallery );
Thanks for looking at this, and sorry for being a crazy person.

Setting Custom Menu Field values in Rightnow API of Oracle

How to set Custom Menu Field values in Rightnow API of Oracle ?
I have a Custom field of data type Menu like :
Custom field Name : user type
Data Type : Menu
Value can be : Free, Paid or Premium
Can any one send me the java code by solving this problem?
Thanks in Advance
The following link is from the Oracle Service Cloud developer documentation. It has an example of setting a contact custom field using Java and Axis2, which would likely give you most of the information that you need in order to set your custom field.
At a high level, you must create an Incident object and specific the ID of the incident that you want to update. Then, you must create the custom field object structure using generic objects (because each site can have its own unique custom fields). Ultimately, your SOAP envelope will contain the node structure that you build through your java code. Since you're trying to set a menu, the end result is that your custom field is a NamedID object. You'll set the lookup name of the menu to one of the three values that you give above.
I'm a C# guy myself, so my example is in C#, but it should be easy to port to Java using the link above as an example too.
public static void SetMenuTest()
{
Incident incident = new Incident();
incident.ID = new ID();
incident.ID.id = 1234;
incident.ID.idSpecified = true;
GenericField customField = new GenericField();
customField.name = "user_type";
customField.dataType = DataTypeEnum.NAMED_ID;
customField.dataTypeSpecified = true;
customField.DataValue = new DataValue();
customField.DataValue.Items = new object[1];
customField.DataValue.ItemsElementName = new ItemsChoiceType[18]; //18 is a named ID value. Inspect ItemChoiceTypes for values.
customField.DataValue.Items[0] = "Free"; //Or Paid, or Premium
customField.DataValue.ItemsElementName[0] = ItemsChoiceType.NamedIDValue;
GenericObject customFieldsc = new GenericObject();
customFieldsc.GenericFields = new GenericField[1];
customFieldsc.GenericFields[0] = customField;
customFieldsc.ObjectType = new RNObjectType();
customFieldsc.ObjectType.TypeName = "IncidentCustomFieldsc";
GenericField cField = new GenericField();
cField.name = "c";
cField.dataType = DataTypeEnum.OBJECT;
cField.dataTypeSpecified = true;
cField.DataValue = new DataValue();
cField.DataValue.Items = new object[1];
cField.DataValue.Items[0] = customFieldsc;
cField.DataValue.ItemsElementName = new ItemsChoiceType[1];
cField.DataValue.ItemsElementName[0] = ItemsChoiceType.ObjectValue;
incident.CustomFields = new GenericObject();
incident.CustomFields.GenericFields = new GenericField[1];
incident.CustomFields.GenericFields[0] = cField;
incident.CustomFields.ObjectType = new RNObjectType();
incident.CustomFields.ObjectType.TypeName = "IncidentCustomFields";
}

PRESTASHOP 1.6 Add a category to a product programmatically

In my module clients can add products to the shop, it will pass by a separate database.
When an admin check the products and validate one, i change the information to a prestashop product.
So i have this code :
$object = new Product();
$object->price = 32;
$object->id_tax_rules_group = 0;
$object->name = array((int)Configuration::get('PS_LANG_DEFAULT') => $creation['title']);
$object->id_manufacturer = 0;
$object->id_supplier = 0;
$object->quantity = 1;
$object->minimal_quantity = 1;
$object->additional_shipping_cost = 0;
$object->wholesale_price = 0;
$object->ecotax = 0;
$object->out_of_stock = 0;
$object->available_for_order = 1;
$object->show_price = 1;
$object->on_sale = 1;
$object->online_only = 1;
$object->meta_keywords = $creation['title'];
$object->active = 1;
$object->description_short = array((int)(Configuration::get('PS_LANG_DEFAULT')) => $creation['description']);
$object->link_rewrite = array((int)(Configuration::get('PS_LANG_DEFAULT')) => $creation['title']);
$object->id_category = 2;
$object->id_category_default = 2;
$object->addToCategories(array(2,13));
//SAVE
$object->save()
The product is saved and has the good information BUT it's not associated to any category.
When i go to my page products, where i can see all products, i see my product and the category is there BUT when i enter the details of the product and i go to the category list nothing is check.
i tried to see more in the code what is happenning and i saw this :
if (!in_array($new_id_categ, $current_categories))
$product_cats[] = array(
'id_category' => (int)$new_id_categ,
'id_product' => (int)$this->id,
'position' => (int)$new_categ_pos[$new_id_categ],
);
And after test the "if" is always true and so the product is association is never created.
I have check and this association does not exist.
I don't know what to do next, or if maybe i need to not use addToCategory, and enter maybe the data myself...
So please help thanks.
The method addToCategories() assigns categories to already created product. In other words you need to call the save() method of the Product class before calling addToCategories();

Prestashop Create Order API

i try to create an API connection so i can create orders in Prestashop via API,
in their DOC:
http://doc.prestashop.com/download/attachments/720902/CRUD+Tutorial+EN.pdf?version=1&modificationDate=1301486324000
there is no information about creating orders, and when i try to create something myself everything fails:
$xml = $webService->get(array('url' => 'http://mysite.com/prestashop/api/orders?schema=synopsis'));
$resources = $xml -> children() -> children();
$resources->children()->id_address_delivery = 1;
$resources->children()->id_address_invoice = 1;
$resources->children()->id_cart = 1;
$resources->children()->id_currency = 1;
$resources->children()->id_lang = 2;
$resources->children()->id_customer = 1;
$resources->children()->id_carrier = 2;
$resources->children()->total_paid = '1';
$resources->children()->total_paid_real = '1';
$resources->children()->total_products = 1;
$resources->children()->total_products_wt = 1;
$resources->children()->conversion_rate = 0.1;
$resources->children()->module = 'cheque';
$resources->children()->payment = 'Cheque';
$xml = $webService->add(array('resource' => 'orders',
'postXml' => $resources->asXML()
));
Gives errors etc, does somebody here has proper documentation available? Or a script which runs in making simple orders?
You need to get the schema then foreach the lines returned, or just supply the values manually.
here is a sample of getting the schema of the selected method.
$xml = $webService ->
get(array('url' => 'http://mysite.com/prestashop/api/customers?schema=blank'));
You need to create Customer, Address, Cart and finally Order. And before creating an order you must have products in the cart and must set id_address_delivery & id_address_invoice.
You can read more details on my blog PrestaShop web service create order errors

Create abstract complexType as an input to an operation for webservice argument class - Coldfusion

I ran into the error:
Unable to create web service argument class [Lcom.verticalresponse.api._1_0.VRAPI_xsd.NVPair;. Error: java.lang.InstantiationException: [Lcom.verticalresponse.api._1_0.VRAPI_xsd.NVPair;. Often this is because the web service defines an abstract complexType as an input to an operation. You must create an actual instance of this type in Java.
while trying to call a WebService. And I have the solution now and I want to post it for anyone else who might be in my situation one day. The issue is that you have to pass a complex structure through coldfusion to the webservice and it doesn't always like to play well.
The answer to this conundrum is how you set up the data as a combination of structures and arrays.
you have to build the data in a very particular manner.
<cfscript>
var ELMResults = StructNew();
var ELMArgs = StructNew();
var MemberData = arrayNew(1);
var ListMember = StructNew();
var session_id = 'the_session_id_provided'
var list_id = 'the_list_id_provided';
var list_name = 'the_list_name_provided';
var list_type = 'the_list_type_provided';
/* set session id */
ELMArgs.session_id = session_id;
/* set member data */
MemberData[1] = StructNew();
MemberData[1].name = "hash";
MemberData[1].value = hash_value;
MemberData[2] = StructNew();
MemberData[2].name = "optin_status";
MemberData[2].value = "2";
MemberData[3] = StructNew();
MemberData[3].name = "first_name";
MemberData[3].value = "Chewbacca";
MemberData[4] = StructNew();
MemberData[4].name = "fax";
MemberData[4].value = "1112223333";
MemberData[5] = StructNew();
MemberData[5].name = "email_address";
MemberData[5].value = email_address;
/* set list member details */
ListMember.list_id = list_id;
ListMember.list_name = list_name;
ListMember.list_type = list_type;
ListMember.member_data = MemberData;
ELMArgs.list_member = ListMember;
ELMResults = VR.editListMember(ELMArgs);
</cfscript>
I hope this helps someone because I was scratching my head for a while.
I found the solution to my own question and posted it here with the question because I couldn't post an answer on the same day of asking the question. I am now simply closing out the thread. I hope this answer helps someone because I was scratching my head for a while with this one.
Cheers, JP