I did my search, and saw tons of people asked this question before. I can't find a clear answer.

I exported my CCK types to files. I want to make calls in my module installer to import the CCK types.

I know I can do it manually on admin page. But I want to have the CCK type imported automatically by the installer. So when I release the module, I don't have to tell users to manually go and import the CCK types.

I thought it would be simple, but I can't find a way to do it. What am I missing? Any help is greatly appreciated.

Thx!

Comments

newbuntu’s picture

Ok, here is my own solution:

   $form_state = array(); 
   $form_state['values']['type_name'] = '<create>';
   
   $myFile = drupal_get_path('module', 'mymodule') .'/test-cck-type.txt'; // your exported cck type file
   $fh = fopen($myFile, 'r');
   $theData = fread($fh, filesize($myFile));
   fclose($fh);
    
   $form_state['values']['macro'] = "$theData";
  
   drupal_execute('content_copy_import_form', $form_state);
newbuntu’s picture

I was attempting to use the same logic to import rules and views. They failed. I wonder if anyone knows why.

Here is what I was trying to do with rules and views:

...
   drupal_execute('views_ui_import_page', $form_state);
...
   drupal_execute('rules_admin_form_import', $form_state);
// i got this error: warning: call_user_func_array() [function.call-user-func-array]: First argument is expected to be a valid callback, 'rules_admin_form_import' was given in D:\Apache2.2\htdocs\ac68\includes\form.inc on line 366.

I notice that 'content_copy_import_form' ends with '_form'. I wonder if drupal_execute() requires that??? How can I get around that?

It take hours and hours to figure out one answer. I've been sharing my findings here. But I am frustrated and tired chasing down all these loose ends. I hope someone can point me the direction, so I can move on with my real work.

thx!

newbuntu’s picture

Well, I'm talking to myself ... :(

I noticed that function_exists($form_id) fails on $form_id='rules_admin_form_import'. Putting on my thinking hat, I thought it might have to do with the module weight, so I set my module weight to 100. It didn't help.

So why can't function_exists() see 'rules-admin_form_import' function? Any theory?

NewZeal’s picture

Hi There,

Just to let you know that you aren't completely talking to yourself and I thank you heartily for this bit of code. It works brilliantly.

Thanks again.

markus_petrux’s picture

That's what often happens when trying to invoke a menu callback that's using the 'file' attribute. In normal operation Drupal loads the module automatically, but if you want to invoke the function, then you need to load the file yourself.

So you may try with:

if (module_exists('rules')) {
  module_load_include('inc', 'rules', ...);
  // Now, the funcion is problaly there.
}

Doubt is the beginning, not the end of wisdom.

dewancodes’s picture

   $form_state = array();
   $form_state['values']['type_name'] = '<create>';
  
   $myFile = drupal_get_path('module', 'mymodule') .'/test-cck-type.txt'; // your exported cck type file
   $fh = fopen($myFile, 'r');
   $theData = fread($fh, filesize($myFile));
   fclose($fh);
   
   $form_state['values']['macro'] = "$theData";
 
   drupal_execute('content_copy_import_form', $form_state);

you are absolutely right !!!

You code works absolutely for me,

Thanks a lot.

Woggers’s picture

I use the method described here and it works flawlessly:

http://blog.daveslist.co.nz/drupal6/2008/10/01/define-content-types-and-...

semperos’s picture

The Install Profile API module has an excellent function to handle all of this very simply: install_content_copy_import_from_file().

You can feed it just the file path, and it will create a new content type, or include file path AND an internal content type name you've already setup, and it will update that one instead (just like the normal CCK UI works).

You'd generally do this in your module's *.install file. If doing it in *.install, you have to make sure the function is available, so here's my hook_install:

<?php
/**
 * Implementation of hook_install().
 */
function MYMODULE_install() {
  // Make sure the file with the function is included.  It lives at "install_profile_api/contrib/content_copy.inc"
  module_load_include('inc', 'install_profile_api', 'contrib/content_copy');
  
  // Get path to the file where I pasted my CCK export, which is inside this module's folder
  $file = __DIR__ . '/my_content_type.cck_import.inc';

  // Call function.  I want to create a new type, so I don't provide a second argument.
  install_content_copy_import_from_file($file);
}
?>

If you read the documentation for this function, you'll see why it's better to use this function than to mess around with drupal_execute yourself.

This module is actually intended to be used when developing installation profiles, but it's got some pretty neat functionality for general installation needs. Check it out!

gollyg’s picture

Nice. Just wanted to note that the __DIR__ magic constant was only added with php 5.3. If you are using < 5.3 (ie probably everyone on <= D6) you will need to use the older format dirname(__FILE__) instead.

Also, the include that contains the cck export code needs to have the opening <?php tag added in order for it to be parsed correctly

giorgio79’s picture

Just what I was looking for.

However, to be able to use that funciton in my module, the user would need to ahve installed the Profile API module correct? :) So I would need to make it a requirement.

hey_germano’s picture

I'm working on a module that needs to import two content types when it's enabled. The code from newbuntu in the first comment works great and makes sense for my project here (thanks!!), but the way I've got it working seems kind of dumb (though it does work) - I'm still trying to figure out how to do things the right way, so a little help here would be much appreciated!

I have two content types to import, so I made a function for each one and put those in my .module file, like this:

function nutrient_flux_calculator_import_flux_helper() {
   $form_state = array(); 
   $form_state['values']['type_name'] = '<create>';
   $myFile = drupal_get_path('module', 'nutrient_flux_calculator') .'/cck/flux_helper.inc'; // exported cck type file
   $fh = fopen($myFile, 'r');
   $theData = fread($fh, filesize($myFile));
   fclose($fh);
   $form_state['values']['macro'] = "$theData";
   drupal_execute('content_copy_import_form', $form_state);
}

function nutrient_flux_calculator_import_nutrient_flux() {
   $form_state = array(); 
   $form_state['values']['type_name'] = '<create>';
   $myFile = drupal_get_path('module', 'nutrient_flux_calculator') .'/cck/nutrient-flux.inc'; // exported cck type file
   $fh = fopen($myFile, 'r');
   $theData = fread($fh, filesize($myFile));
   fclose($fh);
   $form_state['values']['macro'] = "$theData";
   drupal_execute('content_copy_import_form', $form_state);
}

I know enough about programming to know this is lame and redundant, but unfortunately not enough to know how to make this better without blowing everything up (all my ideas have only yielded the WSOD). I just don't know if I make an array, or a foreach, or combine the CCK exports into one file, or something else. Any ideas?

The other part of this module that's kind of awkward is how these functions get run. Right now, I've got a hook_menu function that makes two "install" pages and runs the functions as page callbacks:

function nutrient_flux_calculator_menu() {
  $items = array();
  // install type 1
  $items['nutrient-flux/install'] = array(
    'title' => 'Nutrient flux installer',
    'page callback' => 'nutrient_flux_calculator_import_flux_helper', 
    'access arguments' => array('administer site configuration'),
    'type' => MENU_CALLBACK
  );
  // install type 2
  $items['nutrient-flux/install/2'] = array(
    'title' => 'Nutrient flux installer',,
    'page callback' => 'nutrient_flux_calculator_import_nutrient_flux', 
    'access arguments' => array('administer site configuration'),
    'type' => MENU_CALLBACK
  );
  return $items;
}

So if I enable the module, then visit these URLs, everything works and gets set up correctly. But there's got to be a way to just run those functions without having to do this hook_menu thing, right? I tried putting these in the install file and also tried putting them in a hook_install function in the install file (all WSOD-inducing). Most of the hook_install examples I found were about making database tables - so is the .install file the right place for doing what I'm trying to do? If not, where do they go?

Thanks!

dewancodes’s picture

Is there any solution to import views using install file?
Like here you are discussing about importing content types + fields to be there in that field.

any help will be highly appreciated!

NewZeal’s picture