I would like to programatically (using php) fill out an existing drupal form to create a content type that is included in a contributed module.
Details: The module is SimpleFeed and the content type is Feed. I would like to call the module's functions to accomplish this. The method I am interested in is hook_insert which appears to require vid and nid which I am unsure what these are.
Any help is appreciated.
can you provide a bit more information (which modules?). generally, i'd probably suggest calling the modules functions to create the content type, instead of trying to pass it through a form programatically. this way you don't have to worry about implementation, and can trust that if the module works, it'll work for your script too :)
of course this does tie your module to theirs, so any changes in their functions could affect yours. (but then again, you run that risk if they update their database structure too)
ex.
// your file.php
function mymodule_do_stuff() {
cck_create_field('something'); // as an example, i doubt this
// is a real CCK function :)
}
edit: vid and nid are node ID's, vid is the revision id, and nid is the primary key of a particular node. because this is an actual node, you may have to do two operations.
programatically create a node
you'll have to reference the database for all the exact fields (tables node and node_revisions), but this should get you a basic working node:
$node = (object) array(
'nid' => '', // empty nid will force a new node to be created
'vid' => '',
'type' => 'simplefeed'. // or whatever this node is actually called
'title' => 'title of node',
'uid' => 1, // your user id
'status' => 1, // make it active
'body' => 'actual content',
'format' => 1,
// these next 3 fields are the simplefeed ones
'url' => 'simplefeed url',
'expires' => 'whatever value',
'refresh' => 'ditto',
);
node_save($node);
now i think it should automatically call simplefeed's hook_insert() at this point. if not, then go on to 2. but i'd check to see if it worked out already.
call it yourself!
simplefeed_insert($node);
edit2: drupal_execute() isn't a bad idea either, as you can get back some validation, but this way you don't have to deal with the forms API if you're not comfortable with it. i'm pretty sure node_save() invokes all hooks anyhow, so you should really only have to do step 1 under this method.
The drupal api provides drupal_execute() to do exactly this. I would suggest you avoid calling the functions directly to create the node (unless there is a performance reason). By using drupal_execute() all the proper hooks in other modules will be called and your code is far more likely to continue to work through future versions of drupal.
Note that a classic bug in using this method is not first calling something like
module_load_include('inc', 'node', 'node.pages')
which will load the code for your node creation form.
Calling node_save directly is generally considered deprecated and could leave you with broken code in future versions of drupal.
There is a nice example at this lullabot post
Related
I have a MediaWiki 1.33.0 website with only one extension → ContactPage, with which I can have a simple contact form.
Using HTMLForms template engine (in which the default form-template for ContactPage is written), I have expanded the default form to include a selection menu.
My problem
Selection list array keys and values of this selection menu are written in English inside LocalSettings.php but my site isn't primarily in the LTR English, rather, it is in the RTL Hebrew and I would like them to appear in my site's native language for end users.
My own code pattern
wfLoadExtension( 'ContactPage' );
$wgContactConfig['default'] = array(
'RecipientUser' => 'Admin', // Must be the name of a valid account which also has a verified e-mail-address added to it.
'SenderName' => 'Contact Form on ' . $wgSitename, // "Contact Form on" needs to be translated
'SenderEmail' => null, // Defaults to $wgPasswordSender, may be changed as required
'RequireDetails' => true, // Either "true" or "false" as required
'IncludeIP' => false, // Either "true" or "false" as required
'MustBeLoggedIn' => false, // Check if the user is logged in before rendering the form
'AdditionalFields' => array(
'omgaselectbox' => [
'class' => 'HTMLSelectField',
'label' => 'Select an option',
'options' => [
'X' => 'X',
'Y' => 'Y',
'Z' => 'Z',
],
],
),
// Added in MW 1.26
'DisplayFormat' => 'table', // See HTMLForm documentation for available values.
'RLModules' => array(), // Resource loader modules to add to the form display page.
'RLStyleModules' => array(), // Resource loader CSS modules to add to the form display page.
);
possible solutions
1) Writing selection list array keys and values in Hebrew (which might be a bit messy due to LTR-RTL clashings):
'options' => [
'ס' => 'ס',
'ט' => 'ט',
'ז' => 'ז',
],
2) Translating English selection list array keys and values in client side JavaScript by some similar code:
document.getElementById('select').selectedIndex = 0;
document.getElementById('select').value = 'Default';
My desire
I desire an ordinal backend way to do so, and if there is one, than without an extension
In this discussion, a MediaWiki community member recommended using system message transclution but the chapter dealing with it was very unclear to me; I didn't understand what this is about and how can this help in my situation.
My question
What are the possible ways to translate in MediaWiki from "backend", without an extension?
The localisation system is working perfectly fine in the backend (php), as well in the frontend (JavaScript) parts of MediaWiki → staying with it backend is best as it is more minimal.
Assuming you take a backend only approach:
Translation with a predefined string
If your desired translations already exist in MediaWiki (e.g. on another page of form), you can "simply" re-use the key. So, let's assume, your current additional select field definition looks like this:
'Select' => [
'type' => 'select',
'options' => [
'The english message' => 'value'
]
],
Then, you would change it to something like this:
'Select' => [
'type' => 'select',
'options-messages' => [
'the-message-key' => 'test'
]
],
Please consider the changing of options into the options-messages key.
Also: Change the key the-message-key to the message key you want to reuse.
If you know a page where the message/string is used, you can just open that page with the GET option uselang and the value qqx, in order to see the message key. Example: If the string is used on the login page, simply open the login page with https://example.com/wiki/Special:Userlogin?uselang=qqx to show all the message keys used on the page.
However, one warning when doing that: It is mostly discouraged to re-use existing message keys, especially when they're used on other pages. The keys are translated to hundreds of languages with that specific context in mind. That could also mean, that a translation in a specific language does not fit when the string/message is used on the contact page. So I would suggest to use the second option below.
Translation without a predefined string
Usually it will be done by extension which can provide a specific directory where the JSON files with the message key translations are saved. However, as you're "just" customizing an extension, you need a way to put in the translations for your keys.
So, first of all, let's take over the changes from above. Change your select field definition to be something like:
'Select' => [
'type' => 'select',
'options-messages' => [
'my-fancy-key' => 'test'
]
],
Now, two ways to get the key translated:
On-Wiki
By saving the message on-wiki, the messages can also easily being changed simply by editing the respective page in the wiki. In our example, let's translate the key to english and hebrew:
English: Edit the page MediaWiki:My-fancy-key in your wiki and add the desired text.
Hebrew: Edit the page MediaWiki:My-fancy-key/he in your wiki and add the desired text.
As part of the deployed code
We need to register a directory with JSON files for the translations of these messages. We're using the same configuration variable as extensions would use as well, $wgMessagesDirs, even given that we don't create an extension. Add the following line to your LocalSettings.php:
$wgMessagesDirs['ContactPageCustomization'] = __DIR__ . '/customContactPage';
Now, create a directory customContactPage in the root folder of your MediaWiki installation and put in the following file with the following contents:
en.json
{
"my-fancy-key": "Default"
}
If you want to translate to another language, create a new file with the language code you want to translate to. In hebrew it should be he, so let's create a new language file:
he.json
{
"my-fancy-key": "ברירת מחדל"
}
If you then open the contact page, the message key my-fancy-key should be translated to the english Default and the same (at least based on Google Translate) for hebrew. This is a more stable way of adding custom translations, however, you now also need to take care of translating the keys into the languages you want to support on your own as well. If a key is not translated into the selected language of the user, the default language, english, is used.
I have a need to change a plugin that creates/edits entries to the wp_posts table. Currently, it is lacking in that it cannot target some specific fields. I am endeavoring to edit the plugin so I can change these fields as well with the plugin. Specifics below.
How would I generally target this table then create/edit entries?
I have in mind something like this, which was copied from here.:
$my_post = array(
'post_title' => '#Enter the title#',
'post_content' => '#Enter the Content#',
'post_status' => 'publish',
'post_author' => 1
);
wp_insert_post( $my_post );
I assume this is possible because the plugin I'm hoping to change already makes changes to the wp_posts table. How do I do this? I have programming experience in C#, but my PHP and WP knowledge is severely lacking. I assume there's a few WordPress key functions that I'm looking for, but I simply don't know what they are or how to find them (I might be searching for the wrong terms). wp_insert_post() looks very promising, but the documentation seems to imply that it won't work for my specific needs.
Specifics
I'm using a great plugin called Really Simple CSV importer (RSC), which allows you to create/update posts with a csv. It seems to be able to target nearly every field (e.g. post_title, post_id, post_parent, post_content, _wp_page_template, etc.). This is quite a boon if you have to create hundreds of pages regularly (which I do).
The problem is that it won't target two specific fields, which are titled group_access and tag_list. I put those fields as columns in my csv, but they are not added to the mySQL database, and thus are not changed on the site. I believe these fields are specific to a plugin called iMember360, which is a plugin that ties into an InfusionSoft account.
Naturally, I've tried contacting RSC support, but have received no replies at all. I've spoken to iMember360 support at length, and the best they can give me without doing the work themselves is that they use the action hook import_end to make changes to the table, so if RSC is not using it, then it won't affect those fields. They also say that iMember360 has an import/export function, but it is only for the plugin's specific features, and ties in with the WordPress XML import/export feature. Clearly, this RSC plugin does not do that.
Regardless of these limitations, it seems to me like if the field exists in the table, then you should be able to edit it, so I tend to think that the RSC plugin is simply lacking in this functionality, probably only targeting WP default fields only.
What I've tried:
I have tried editing the plugin PHP directly, with the assumption that the plugin simply does not have an entry for the group_access and tag_list fields.
One of the PHP files contained:
// (string, comma separated) name of post tags
$post_tags = $h->get_data($this,$data,'post_tags');
if ($post_tags) {
$post['post_tags'] = $post_tags;
}
I simply copied and pasted it right above it and changed post_tags to group_access. It didn't work.
I also found, and added to:
$attachment = array(
'post_mime_type' => $mime_type ,
'post_parent' => $this->postid ,
'post_author' => $this->post->post_author ,
'post_title' => $title ,
'post_content' => $content ,
'post_excerpt' => $excerpt ,
'post_status' => 'inherit',
'menu_order' => $this->media_count + 1,
////////// added
'group_access' => $group_access ,
'tag_list' => $tag_list ,
//////
);
That didn't do anything either.
There are two ways to edit the wp_posts table that I know of. The first is with the wp_update_post() and wp_insert_post() functions. These are typical WP functions that are used like any others. You just have to pass the correct parameters. For example:
$my_post = array(
'ID' => $updatePostID, // User defined variable; the post id you want to update.
'post_title' => 'Update Title',
'post_content' => 'Update Content',
);
// Update the post into the database
$post_id = wp_update_post( $my_post, true ); // Returns 0 if no error; returns post id if there was an error.
// Check if table was updated without error. For debugging. Remove from your code if it all works, before publishing.
if (is_wp_error($post_id)) {
$errors = $post_id->get_error_messages();
foreach ($errors as $error) {
echo $error;
}
}
Simply pass an array with the predefined field names to the functions and they will then run correctly. The update function is for updates, naturally, and the insert function creates new table entries (rows). There is a limitation, however. These two functions will only operate on the WP predefined fields. So, if your table contains some custom fields, then you will have to use the $wpdb class.
The other way to update your mySQL tables from WordPress is to use the $wpdb class directly. This class is far more expansive than the wp_update_post() and wp_insert_post() functions. The first difference is that it can edit many other mySQL tables, not just the wp_posts table. It can also edit non-WP fields. For example:
global $wpdb; // This calls the use of the class. I actually do not think this is necessary, but I do it anyway.
$dbresult = $wpdb->update($wpdb->posts, // Returns 0 if no errors. Post ID if errors occurred.
// Notice posts instead of wp-posts. Prefixes are not necessary with this class.
['post_title' => 'Update Title',
'post_content' => 'Update Content',
'custom_field' => $customField, ], // User defined table column and variable.
['ID' => $updatePostID, ]); // User defined variable; the post id.
if (false === $dbresult) {
echo 'An error occurred while updating...';
$errors = $post_id->get_error_messages();
}
I'm not very familiar with either of these options, but there seems to a massive difference in the width of functionality, so there may be considerations you should take before using one over the other. I've asked a question to that end: https://wordpress.stackexchange.com/q/259043/38365 One reply says:
Downsides of $wpdb are that you do need to know SQL and you need to be conscious of normal data sanitization and when to use prepare() and what functions already prepare your statement which are hardly downsides at all. The $wpdb Class is by nature more powerful than any of the default WordPress functions because you have access to all the data, custom or not, assuming you know the proper SQL to get, modify, or remove it.
TL;DR $wpdb is more powerful but less friendly and forgiving.
That makes sense to me. Basically, don't fiddle with $wpdb unless you know what you are doing or absolutely have to.
Once I've identified identified the email addresses of my list segment (using get_emails() custom function, I am setting up my list segment as follows:
$batch = get_emails();
//now create my list segment:
$api->listStaticSegmentAdd(WEDDING_LIST_ID, 'new_wedding_guests');
$api->listStaticSegmentMembersAdd(WEDDING_LIST_ID, 'new_wedding_guests', $batch);
//do I build vars for a campaign?
$options = array (
'list_id' => WEDDING_LIST_ID, //What value id's my list segment?
'subject' => 'Alpha testing.',
'from_email' => 'wedding#juicywatermelon.com',
'from_name' => 'Pam & Kellzo',
'to_name' => $account->name,
);
From here can I use a basic campaign and send it?
$content['text'] = "Some text.";
$content['html'] = get_link($account);
$cid = $api->campaignCreate('regular', $options, $content);
$result = $api->campaignSendNow($cid);
I'm not sure if I'm understanding the api documentation correctly. I also tried 'list_id' => 'new_wedding_guests'; which failed to create a campaign.
Thanks!
I'll assume this is test code and just make the cursory mention of how you probably don't need to be creating a new Static Segment every time. However, your call to add members is not going to work. Per the listStaticSegmentMembersAdd documentation, you should be passing the static segment id, not the name of it. Also note that the docs cross-reference themselves when input params can come from other calls - that parameter there is a good example (it also happens to be returned by listStaticSegmentAdd).
Your options for campaignCreate look like a good start. The documentation for it has examples below - those examples are included in the PHP MCAPI wrapper you likely downloaded. As per above, the list_id you need is the one for the list you used in the listStaticSegment calls (also linked in the documentation).
Now the real key - further down in the campaignCreate docs is the segment_opts parameter - that is how you control segmentation. Follow the link it gives you and you'll find tons of info on the ways you can do segmentation, including using a static_segment.
Hopefully all of that made sense, if not, take a step back and check out these links (and play with segmentation in the app), then it should:
Introduction to MailChimp List Management
How can I send to a segment of my list?
Our Release Info on how Static Segments are used
I have a few jQueryUI draggable objects that represent nodes generated on my front page in Drupal.
I want to grab when a user drops an element and save the x/y coordinates to the server so when the next user opens the page it will still be where it was last left at.
I created two integer fields, homex and homey, but I can't seem to figure out or find enough documentation to learn how to tell Drupal to update the values for a given node.
I'm fairly familiar with how to create modules in Drupal, and ajax in general - but combining the two in this case is perplexing me.
Can someone help me understand how to attach to Drupal so I can save the coordinates dynamically?
What would be preferable is if I could just write a simple handler module for Drupal that takes the x/y pair in a get/post request then updates them in the database and responds with a success/json. Really if it wasn't being done in Drupal this would be a fairly simple setup.
It seems all I had to do was create a hook_menu() and a hook_ajax_callback() (sorry couldn't find a link) in a module.
Here's what I ended up with (more less, leaving in three different return methods I was playing with):
<?php
function homepage_coords_menu(){
return array(//$items
'homepage_coords/%node/%/%' => array(
'page callback' => 'homepage_coords_ajax_callback',
'page arguments' => array(1,2,3),
'access callback' => TRUE,
'type' => MENU_CALLBACK,
)
);
}
function homepage_coords_ajax_callback($node,$x=0,$y=0){
if(!is_numeric($x) || !is_numeric($y)){
ajax_deliver(json_encode(array(
'status'=>'fail'
)));
}
$node->field_homepagex = array('und'=>array(array('value'=>$x)));
$node->field_homepagey = array('und'=>array(array('value'=>$y)));
node_save($node);
ajax_deliver(json_encode(array(
'status'=>'win'
)));
}
?>
When you say that you are familiar with ajax, you mean jquery's ajax or Drupal 7 ajax framework. You can read more about the Drupal 7 Ajax here http://drupal.org/node/752056
I suppose homex is a hidden form element. Maybe you could hook_form_alter it, adding a #ajax attribute with an ajax callback triggered by a "change" event for example or any other Jquery event, and in that ajax callback, execute node_form_submit_build_node
I am using SugarCRM Version 5.2.0k (Build 5837). I would like to be able to set a default home page (with dashlets I've created myself) that will be the same for all users, can anyone advice on best way to do this?
Thanks in advance for your help
I'd like to know how to do this too... see here for some ideas, but it's clear that it's not a supported feature.
I wonder if you can write a module that installs a hook for post user creation (assuming that this hook is provided) and then populate the appropriate part of the user preferences table when the hook is invoked. Of course, your module will probably break with each upgrade of SurgarCRM, so this might be more trouble than it i worth.
Edit:
I had a look at the Dash Manager module that is referenced in the thread I linked to above. It's approach is to copy the preferences of the admin user to all other users when the administrator clicks a link in the admin page. So, the admin user is used as a sort of template for other users. Rudimentary solution, but not a bad start - using a template user and treating the preferences (as stored in the DB table) as opaque seems like the way to go.
It's quite easy to do it.
I have done it in SugarCRM 6.5.23.
Here I have mentioned steps to do it:
Just copy sugarcrm_root/modules/Home/index.php and paste it in SugarCRM_root/custom/modules/Home/index.php.
Now you can customize it's behavior as you want.
You can remove default dashlets and add your own dashlets by creating one file at SugarCRM_root/custom/modules/Home/dashlets.php and add this code in it:
<?php
unset($defaultDashlets);
$defaultDashlets = array(
'CustomDashlet' => 'ModuleName',
'UpcomingAppointmentsDashlet' => 'Meetings', //Example
);
Once you do this thing still you have 3 dashlets left in your hook code you can remove it if it's needed code for that hook is like this:
$dashlets[create_guid()] = array(
'className' => 'iFrameDashlet',
'module' => 'Home',
'forceColumn' => 0,
'fileLocation' => $dashletsFiles['iFrameDashlet']['file'],
'options' => array('titleLabel' => 'LBL_DASHLET_DISCOVER_SUGAR_PRO',
'url' => '...',
'height' => 315,
));
Hope this will help you. :)