Posts Tagged ‘php code’

Drupal 7: Batch insert nodes with Drush

Posted on:Wednesday, February 9th, 2011 by Ashish Datta

Well D7 has been out for a little while now and we finally got a chance to use it on a site this week.

Anyway, this site is one of the heavier Drupal sites we’ve done and it involved loading ~200+ nodes of data just to set things up. This presented two problems, how to batch load data and then how to load custom content types with several custom fields.

The Drupal module documentation has example code for adding a node with drupal_exeucte here but it doesn’t deal with how to set custom fields on your content type. On top of this, drupal_execute has been renamed to drupal_form_submit in Drupal 7 and the function signature has changed a bit.

Anyway, I dug around a bit and finally managed to get this working. You’ll obviously need Drush installed for the following code to work but you could rip it out and use it outside a Drush command. I was looking to basically replicate the “load-data” task from Symfony so that I could seed my Drupal database with Nodes at any point so I chose to make this a Drush command.

Here’s what you need:

- You’ll need a module to hold the Drush task. I used Module Builder to generate my scaffolding.
- Create a file named [modulename].drush.inc in your module directory
- Here is the code I’m using for [modulename].drush.inc Replace “cm” with the name of your module:


/**
* Implementation of hook_drush_command().
*/

function cm_drush_command() {

        // callback is the function that will be called when the command is executed
	$items['load-rep-data'] = array(
	    'callback' => 'cm_load_rep_data',
            'description' => 'Loads the representative data.',
            'bootstrap' => DRUSH_BOOTSTRAP_DRUPAL_FULL,
	);

	return $items;
}

function cm_load_rep_data( ){
   // you need this to autoload the functions to create nodes
   module_load_include('inc', 'node', 'node.pages');

  // do some business logic to load your data from where it is
  foreach( $arr as $res ){

    // define the custom node type
    $node = array('type' => 'representative');

   // set up the form array
   $form_state = array();

   // set the title of the node
   $form_state['values']['title'] = $res["title"];

   // set a custom field that is a text type
   $form_state['values']['field_first_name']['und']['0']['value'] = $res["first_name"];

   // set a long text field and enable full_html - NOTE you'll need to allow anonymous users to use this for Drush to work
   $form_state['values']['body']['und']['0']['format'] = 'full_html';
   $form_state['values']['body']['und']['0']['value'] = $res["bio"];

  // set some custom select fields
  $form_state['values']['field_house_committees']['und'][ 0 ] = 34;
  $form_state['values']['field_house_committees']['und'][ 0 ] = 37;

  // can't leave this out or the form wont save
  $form_state['values']['op'] = t('Save');

  // actually try and "submit" the form
  drupal_form_submit('representative_node_form', $form_state, (object)$node);

  // printing from Drush is easy
  drush_print( $res["title"] );
  }
}

Thats about it.

With Firebug, it’s really easy to see the field names and the values that you can set by just looking at a form to create whatever type of node you want.

drupal_form_submit can also be used to “submit” any other type of form in Drupal.

An open question is how to “fill out” an ImageField field via the command line since nothing is actually going to be uploaded.

Received problem 2 in the chunky parser

Posted on:Sunday, December 26th, 2010 by Ashish Datta

I was using cURL in PHP to POST some data to a URL earlier tonight and ran into this problem.

With VERBOSE on cURL was erroring with the following error:

"Received problem 2 in the chunky parser"

After some Googling it turns out this is a problem with how some servers respond with chunked encoding.

A simple fix for this is to set the HTTP version cURL is using to 1.0:

curl_setopt($ch, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0 )

It’s not pretty but hey it works!

Google Calender embed missing events

Posted on:Tuesday, August 4th, 2009 by Ashish Datta

So we decided to use the Google Calendar API in one of our applications to allow users to easily view and export events from outside the app. In general, the API was working well – I was using the Zend library to interact with Google and things seemed fine.

That was until I tried to embed the calendar using Google’s iframe embed code. For some reason, events weren’t showing up in the embeded iframe calendar even though they were showing up in the actual calendar on calendar.google.com. Even stranger, the events were present in a JSON object on the embeded page and they were showing up in the RSS feed for the calendar.

After literally days of debugging and experimenting I finally found out the culprit.

For some reason, events created via the API that start and end at exactly the same time – say a start date of 08-05-2009 10:00:00 and an end date of 08-05-2009 10:00:00 don’t render on the embeded iframe calendar.

What is even more bizarre is that if you create an event via the web interface that starts and ends at the same time, it will render correctly on an embeded calendar.

Anyway, that was weird. All the events without explicit start and end times now last a grand total of one minute.

PS. Kudos to Daum for finding a constant for PHP’s date() function to generate RFC3339 timestamps.

Use like so:

  $date = date(DATE_RFC3339, $timestamp);

To get back a valid RFC3339 for the Google Calendar API.

FOSS Fridays: OpenSSL in PHP

Posted on:Friday, July 31st, 2009 by Ashish Datta

Well Twitter has “Follow Fridays” so I thought we should do FOSS Fridays. I don’t really have a plan for this and it might not last but let’s see where it goes.

In the last few days a couple of people have asked for tips on how to use OpenSSL from PHP. So here is a snippet on how to do it. This comes out of an application that provides a shared authentication system between our client’s LDAP system and their partner’s systems.

It works like so:

  1. Users login to the application using their LDAP credentials.
  2. When the users request to visit the partner site, our system packages up their login information, encrypts it, signs it, and shoots it along with the user to the partner site.
  3. Next, the partner checks if the user has an account and if they do it logs them in. Otherwise, it creates them a new account and logs them in.

All of this is done transparently so that the user doesn’t know they’ve actually left the original site.

Here is the code to do it. PS. it’s from a Symfony application.

$user = $this->getUser();

$profile = $user->getProfile();

if(is_null($profile)){ die("Could not get user profile?"); }

$email = $profile->getEmail();

$firstName = $profile->getFirstName();

$lastName = $profile->getLastName();

$password = $request->getParameter("password");

$keyText = file_get_contents(sfConfig::get("sf_root_dir") . "/" . sfConfig::get("app_their_public_key"));

$theirPublicKey = openssl_pkey_get_public($keyText);

$keyText = file_get_contents(sfConfig::get("sf_root_dir") . "/" . sfConfig::get("app_our_private_key"));

$outPrivateKey = openssl_pkey_get_private($keyText);

$arr = array();

$arr["U_EMAIL"] = $email;

$arr["U_PASSWORD"] = $password;

$arr["U_FIRST_NAME"] = $firstName;

$arr["U_LAST_NAME"] = $lastName;

$arr["RL_E"] = $this->generateUrl("ps_error", array(), true);

$arr["RL_S"] = "PRIVATE URL";

$arr["ETIME"] = time() + 60;

$queryString = http_build_query($arr);

$res = openssl_sign($queryString, $signature, $outPrivateKey);

if(!$res){ throw new sfException("Could not sign the payload!", 1); }

$t = openssl_pkey_get_details($theirPublicKey);

$t = (int) ($t['bits'] / 8 ) - 11;

$l=strlen($queryString);

$cryptPayload = '';

for ($i=0; $i<$l; $i+= $t) {

  $block = substr($queryString, $i, $t);

  if (!openssl_public_encrypt($block,$tS, $theirPublicKey)){
    throw new sfException('failed encrypt', 1);
   }

  $cryptPayload .= $tS;
}

$this->encodedSignature = base64_encode($signature);

$this->encodedData = base64_encode($cryptPayload);

The net result of all of this is an encrypted payload with the user’s credentials and a signature of the payload. The payload is encrypted with “their” public key and then signed with “our” private key. This ensures that only they can open the package and only we can generate valid signatures.

Happy Friday!

Yahoo BOSS is sahweet!

Posted on:Wednesday, August 13th, 2008 by Ashish Datta

A couple of weeks ago I ran across this article on Techcrunch.

Basically, a Yahoo! engineer used Yahoo Boss! and the Google App engine to make a “who,what,where,when” answering service. Since I want one I took a look at the code, but since its on the GAE the code is in Python for the GAE.

Anyway, since its like 50 lines of code I decided to take a look at BOSS and port it over to PHP. The quick and dirty PHP clocks in at 200 lines and is available for testing. The PHP returns JSON code with an optional callback specified with c=

Feel free to use it for whatever – just play nice

It might even make it into a super secret Wikia framework!

Code is available here.

Vik does a really good job of explaining how the process works. Unfortunately, its not particularly consistent or accurate. But it is pretty neat and considering its only 200 lines a good demonstration of thinking outside the box.