Send a message to an updated number in Silverstripe - silverstripe

I have a SendSMS() function in customer.php file, and I am updating the MobileTelephone field in the database. When the mobile number is updated a message should go to the new number. In my case, database updates and message goes to the previous number. I want to make them go to the new number. Any suggestions?
Below is my function:
Below function is in MyAccountPage.php
function changeMyContactDetails($data,$form){
$member = Customer::CurrentUser();
//debug::show($member);
if($member){
if($data['MobileTelephone']!=$member-> MobileTelephone){
//sleep(10);
$verified = array(
'IsMobileVerified' => 'N',
//'MobileVeryDate' => date(MYSQL_DATETIME, strtotime(SS_Datetime::now()))
);
//sleep(10);
$member->update($verified);
$member->write();
//sleep(10);
$member = Customer::CurrentUser();
$member->SendSMS();
}
$form->saveInto($member);
$member->write();
}
return $this->redirectBack();
}

You have not altered member before sending the message.
use Form::saveInto first, not after sending.
This could also be done directly from member, in onAfterWrite(), using $this->isChanged('MobileTelephone').
That way it is centralised so it doesn't matter which form/process updates the number.
It is best to achieve this through an Extension: http://docs.silverstripe.org/en/developer_guides/model/extending_dataobjects/

Related

smarty phpunit empty fetch

I need help please.
I'm using Smarty with PHPUnit, and I have troubles.
For example:
In some checks, I call fetch function many times, and I only receive right the first call, the others only return empty. Why???
I let some code here as an example:
/**
* #dataProvider provider_test
*/
public function test_field($field) {
// with this I instance smarty
$front = $this->get_template();
$front->assign('function', 'fb_user_field');
$front->assign('field', $field);
// this fetch only return right widh the first value of field
$result = $front->fetch('tests/generic.tpl');
$this->assertNotNull($result);
}
public function provider_test() {
return array(
array('field' => 'subdomain'),
array('field' => 'login')
);
}
I check $field and in every iteration receive the correct value, but after the first one, fetch return only empty.
Why???? Thanks!!!
My suggestion is to use the MakeGood or similar to step by step debug your php code. Otherwise it is guess and check till you die!
Here's some links
http://blog.loftdigital.com/running-phpunit-tests-in-eclipse-pdt
http://www.youtube.com/watch?v=1qnWL52wt58
I used to spend hours guess and check with phpunit until I discovered MakeGood. Hope it helps!

Drupal 7 node_save not saving computed fields during cron

I have a Drupal content type which contains a number of computed fields. Some (but not all) items are being added to this content type via a cron-triggered RSS feed importer. I'm trying to trigger computed field generation for new items in hook_cron. The following code grabs all items that haven't been tagged as 'submitted', loads and re-saves the node, and then marks the node as 'submitted'.
$query = db_select('node', 'n');
$query->fields('n', array('nid'));
$table_alias = $query->join('field_data_field_submitted', 'r', 'n.nid = r.entity_id AND r.field_submitted_value = 0');
$result = $query->execute();
foreach ($result as $record){
$q = $record->nid;
$n = node_load($q);
node_save($n);
$query = db_update('field_data_field_submitted')
->fields(array('field_submitted_value' => 1))
->condition('entity_id', $q)
->execute();
}
This code works the way I expect it to if I call it from a module-generated page (created using hook_menu with a page callback function). Nodes are resubmitted, and the computed field data is generated. When I put this code in my hook_cron function, the query works, it loops through the records and updates the 'submitted' value, but the computed fields are not computed. I'm confused as to why this would not get triggered in cron. Any help?
Doh! Finally realized that this was completely my own doing. Due to the nature of this content type, where we allow anonymous users to create new content, but explicitly do not trigger the computed fields when they create the content (long story, but short form is that authenticated users then verify & enhance this content, which is where the computed fields come in). So, as I was setting up the initial content, I disabled the computed fields for anonymous users (if $user->uid > 0), and completely forgot about that. Once I tweaked that logic to allow computed fields to be processed on import (triggering it with a field that has a value for the imported content, but not for other content), the problem was solved.
The cron run has access to the full bootstrap so there's no logical reason why your code would produce different results in that context.
That said, you're only updating the field_data_field_submitted table when you also need to update the field_revision_field_submitted table, so that might somehow account for the discrepancy.
Drupal provides an API for the field system so that these sorts of problems can be avoided completely. The same code you've used, rewritten the 'Drupal' way, would be:
$query = new EntityFieldQuery;
$query->entityCondition('entity_type', 'node')
->fieldCondition('field_submitted', 'value', 0);
$results = $query->execute();
if (!empty($results['node'])) {
$nodes = node_load_multiple(array_keys($results['node']));
foreach ($nodes as $node) {
$node->field_submitted[$node->language][0]['value'] = 1;
node_save($node);
}
}
I can't think of a good reason why the above code would fail on cron either so it might be worth giving it a whirl.

Need advice to get my logic correct in d7

Goal: Is to save information of a node which gets updated. We need to gather the node id of the node which is updated and also the user names of people who have bookmarked it.
Implementation:
I have managed to get the both this detail using flags and rules module. I made a custom module which implemented the hook to get this info.
I am getting stuck here:
Now I need to save the user name and the node id. I am still deciding if I want to use fields or the db layer.
One username can have multiple node id saved.
Now the problem is I don't know for sure how many nodes will be enough. It depends on the user. It can be 5 can be 500 or even 5000 node ids that might need to be saved for one user.
So how do I make provision for this ?
So I am stuck with the logic. How should I use the db layer or the fields in custom content type to save this ? and how should I do it ?
Please advice. I am using d7.
custom module code
/*
* Implementation of the hook_rules_action_info()
*
*/
function customvishal_rules_action_info()
{
$actions = array(
'customvishal_action_userdetail' => array(
'label' =>t('Custom function to send notifications'),
'group'=>t('Cusotm Code for sending notifications'),
'parameter'=> array(
'account'=> array(
'type'=>'user',
'label'=>t('Going to get user list'),
),
// for the node
'productdetail'=> array(
'type'=>'node',
'label'=>t('Passding the node data'),
),
)
),
);
return $actions;
}
/*
* The action function for the rules exampled hello world
*
*/
function customvishal_action_userdetail($account,$productdetail)
{
drupal_set_message(t('This user #username! has flagged it',
array('#username' => $account->mail)));
drupal_set_message(t('This node #nid has got updated',
array('#nid' => $productdetail->nid)));
// The above takes care of the node and the user information later I will put
// it in a db or something like that.
// end of the function customvishal_action_userdetail
}
It really seems like you should be using hook_node_update() and hook_node_insert() to for access to nodes that have just been added or updated.
If you wanted access to the node data just before it was saved, then hook_node_presave() would be the one to use.
I don't think you need presave though because you mentioned you needed the node ID, and presave does not have that for new nodes yet.
Here's a way to process new and updated nodes. The first 2 functions just hook into the right place and route the node to the 3rd function.
<?php
// hook into node inserts
function customvishal_node_insert($node) {
if ($node->type == 'mynodetype') {
customvishal_handle_data($node);
}
}
// hook into node updates
function customvishal_node_update($node) {
if ($node->type == 'mynodetype') {
customvishal_handle_data($node);
}
}
// custom handler for the nodes
function customvishal_handle_data($node) {
// load a user object of the node's author
$author = user_load($node->uid);
// now do what we need to do with $node and $user data
}
Remember you need to clear the Drupal cache for new hooks in your module to work in D7.

How to get Drupal Rules settings?

How to programmatically retrieve configuration of the specific rule?
I tried
$settings = rules_config_load('RULE_NAME');
It returns very basic info (name, ID etc) and empty "settings" array.
Cant also get it directly from DB .
It is stored in serialized array that can not be fully processed with the
unserialize() function
I got the same issue and end up here, here is a solution i found, you need to call actions() on your rule to access settings:
$rule = rules_config_load('RULE_NAME');
foreach ($rule->actions() as $action) {
$settings[] = $action->settings;
}

Multiple concurrent database connections in drupal 7

I'm writing a wrapper class for my drupal 7 site which lets me connect to and query my phpbb database.
When connecting to an external data source (as per drupal documentation) you have set the active db, run the query, then set the active db back to the default.
e.g.
db_set_active('phpbb');
$result = db_query($sql,$args,$opts);
db_set_active();//back to default
But is there any way to use drupal's database wrapper to create a brand new connection which can be permanently set to the new database without having to do this switching back-and-forth nonsense? surely we can handle connections to multiple databases concurrently.
I have done some googling but haven't found anybody trying to do this as yet.
Typical. 5 minutes after posting i figure it out... so, for future googlers:
Basically, you don't use db_query, instead you run the query on your connection without setting the active link.
you can figure this out by looking at how db_query works:
http://api.drupal.org/api/drupal/includes--database--database.inc/function/db_query/7
So it looks like this:
$target='default';
$key = 'phpbb';
$phpbb = Database::getConnection($target,$key);
$result = $phpbb->query($sql,$args,$opts);
This assumes you have a database configured in your settings.php like the following:
$databases['phpbb']['default'] = array(
'driver' => 'mysql',
'database' => 'forum',
'username' => 'username',
'password' => 'password',
'host' => 'mysql.host.com',
'prefix' => 'phpbb3_'
);
Database::addConnectionInfo() perhaps?
This method allows the addition of new connection credentials at
runtime. Under normal circumstances the preferred way to specify
database credentials is via settings.php. However, this method allows
them to be added at arbitrary times, such as during unit tests, when
connecting to admin-defined third party databases, etc.
If the given key/target pair already exists, this method will be
ignored.
The definition for getConnection cites a different order for arguments than used above.
function getConnection($target = 'default', $key = NULL)
This is sadly different from Database::addConnectionInfo() which is
public static function addConnectionInfo($key, $target, $info)
Also, on DB_select, the $key is not a parameter, though it is in the options array:
function db_select($table, $alias = NULL, array $options = array()) {
if (empty($options['target'])) {
$options['target'] = 'default';
}
return Database::getConnection($options['target'])->select($table, $alias, $options);
}
while
final public static function getConnection($target = 'default', $key = NULL) {
so this implies that the 'master' or 'slave' or 'default' is always used as set, but not the key to the alternative database/schema, requiring the db_set_active('...'); and db_set_active(); around the db_select.
Since calls to other dbs can easily be required within the processing of the db_select (such as devel calls or calls in alters), this is inflexible design. Changing this call:
return Database::getConnection($options['target'])->select($table, $alias, $options);
to add the Key parameter (it is already spec'd as an argument!!) is needed but insufficient so far as I can now see.

Resources