? flag-ctools-2.patch
? flag-ctools-3.patch
Index: flag.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flag/Attic/flag.inc,v
retrieving revision 1.1.2.30
diff -u -p -r1.1.2.30 flag.inc
--- flag.inc	14 Mar 2009 06:13:54 -0000	1.1.2.30
+++ flag.inc	18 Aug 2009 15:41:29 -0000
@@ -234,23 +234,29 @@ class flag_flag {
 
   /**
    * Validates a flag settings
+   * 
+   * @return
+   *   TRUE if flag settings are valid.
    */
   function validate() {
-    $this->validate_name();
+    return $this->validate_name();
   }
 
   function validate_name() {
     // Ensure a safe machine name.
     if (!preg_match('/^[a-z_][a-z0-9_]*$/', $this->name)) {
       form_set_error('name', t('The flag name may only contain lowercase letters, underscores, and numbers.'));
+      return FALSE;
     }
     // Ensure the machine name is unique.
     if (!isset($this->fid)) {
       $flag = flag_get_flag($this->name);
       if (!empty($flag)) {
         form_set_error('name', t('Flag names must be unique. This flag name is already in use.'));
+        return FALSE;
       }
     }
+    return TRUE;
   }
 
   /**
Index: flag.install
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flag/Attic/flag.install,v
retrieving revision 1.2.2.32
diff -u -p -r1.2.2.32 flag.install
--- flag.install	22 Jun 2009 22:46:51 -0000	1.2.2.32
+++ flag.install	18 Aug 2009 15:41:29 -0000
@@ -116,6 +116,9 @@ function flag_schema() {
   $schema = array();
 
   $schema['flags'] = array(
+    'description' => t('Flag definitions.'),
+    // CTools information.
+    'export' => _flag_ctools_export_scehma(),
     'fields' => array(
       'fid' => array(
         'type' => 'serial',
Index: flag.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flag/Attic/flag.module,v
retrieving revision 1.11.2.72
diff -u -p -r1.11.2.72 flag.module
--- flag.module	15 Jun 2009 20:05:42 -0000	1.11.2.72
+++ flag.module	18 Aug 2009 15:41:30 -0000
@@ -58,6 +58,25 @@ function flag_menu() {
     'file' => 'includes/flag.admin.inc',
     'type' => MENU_LOCAL_TASK,
   );
+
+  $items['admin/build/flags/%flag/export'] = array(
+    'title' => 'Export',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('flag_export_flag', 3),
+    'access arguments' => array('administer flags'),
+    'type' => MENU_CALLBACK,
+    'file' => 'includes/flag.admin.inc',
+  );
+
+  $items['admin/build/flags/import'] = array(
+    'title' => 'Import',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('flag_import_flag'),
+    'access arguments' => array('administer flags'),
+    'type' => MENU_LOCAL_TASK,
+    'file' => 'includes/flag.admin.inc',
+  );
+
   $items['flag'] = array(
     'title' => 'Flag',
     'page callback' => 'flag_page',
@@ -428,6 +447,25 @@ function flag_node_type($op, $info) {
 }
 
 /**
+ * Implementation of hook_schema_alter().
+ *
+ * Add CTool's export information to the flags table.
+ */
+function flag_schema_alter(&$schema) {
+  if (empty($schema['flags']['export'])) {
+    $schema['flags']['export'] = _flag_ctools_export_scehma();
+  }
+}
+
+/**
+* Menu callback; Load a flag object.
+*/
+function flag_load($name) {
+  return flag_get_flag($name);
+}
+
+
+/**
  * Menu callback for (un)flagging a node.
  *
  * Used both for the regular callback as well as the JS version.
@@ -833,6 +871,9 @@ function flag_get_counts($content_type, 
  *   The the flag name.
  * @param $fid
  *   The the flag id.
+ * @return
+ *   The flag object if found or FALSE.
+ *
  */
 function flag_get_flag($name = NULL, $fid = NULL) {
   $flags = flag_get_flags();
@@ -848,6 +889,7 @@ function flag_get_flag($name = NULL, $fi
       }
     }
   }
+  return FALSE;
 }
 
 /**
@@ -890,6 +932,12 @@ function flag_get_flags($content_type = 
     // Add code-based flags provided by modules.
     $default_flags = flag_get_default_flags();
     foreach ($default_flags as $name => $default_flag) {
+      // We might get the code from CTools boject export, so preapre it to be
+      // processed.
+      if (!is_array($default_flag->roles)) {
+        $default_flag->roles = explode(',', $default_flag->roles); 
+      }
+      
       // Insert new enabled flags into the database to give them an FID.
       if ($default_flag->status && !isset($flags[$name])) {
         $default_flag->save();
@@ -951,7 +999,8 @@ function flag_get_default_flags($include
   foreach (module_implements('flag_default_flags') as $module) {
     $function = $module . '_flag_default_flags';
     foreach ($function() as $config) {
-      $flag = flag_flag::factory_by_array($config);
+      // Cast config to array as it might be an export object.
+      $flag = flag_flag::factory_by_array((array)$config);
       $flag->module = $module;
       // Add flags that have been enabled.
       if ((!isset($flag_status[$flag->name]) && (!isset($flag->status) || $flag->status)) || !empty($flag_status[$flag->name])) {
@@ -1111,3 +1160,19 @@ function flag_get_token($nid) {
 function flag_check_token($token, $seed) {
   return drupal_get_token($seed) == $token;
 }
+
+/**
+ * Helper function to return CTools export information.
+ */
+function _flag_ctools_export_scehma() {
+  return array(
+    'key' => 'name',
+    'identifier' => 'flag',
+    'default hook' => 'flag_default_flags',
+    'api' => array(
+      'owner' => 'flag',
+      'minimum_version' => 1,
+      'current_version' => 1,
+    ),
+  );
+}
\ No newline at end of file
Index: includes/flag.admin.inc
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/flag/includes/Attic/flag.admin.inc,v
retrieving revision 1.1.4.2
diff -u -p -r1.1.4.2 flag.admin.inc
--- includes/flag.admin.inc	17 Mar 2009 02:05:24 -0000	1.1.4.2
+++ includes/flag.admin.inc	18 Aug 2009 15:41:30 -0000
@@ -26,6 +26,7 @@ function theme_flag_admin_page($flags, $
     $ops = theme('links', array(
       'flags_edit' =>  array('title' => t('edit'), 'href' => "admin/build/flags/edit/". $flag->name),
       'flags_delete' =>  array('title' => t('delete'), 'href' => "admin/build/flags/delete/". $flag->name),
+      'flags_export' =>  array('title' => t('export'), 'href' => "admin/build/flags/". $flag->name ."/export"),
     ));
 
     $roles = array_flip(array_intersect(array_flip(user_roles()), $flag->roles));
@@ -53,6 +54,7 @@ function theme_flag_admin_page($flags, $
     if (!isset($flags[$name])) {
       $ops = theme('links', array(
         'flags_enable' =>  array('title' => t('enable'), 'href' => "admin/build/flags/edit/". $flag->name),
+        'flags_export' =>  array('title' => t('export'), 'href' => "admin/build/flags/". $flag->name ."/export"),
       ));
 
       $roles = array_flip(array_intersect(array_flip(user_roles()), $flag->roles));
@@ -444,3 +446,121 @@ function _flag_clear_cache() {
   // changed.
   menu_rebuild();
 }
+
+/**
+ * Import a flag form.
+ */
+function flag_import_flag() {
+  if (!module_exists('ctools')) {
+    $form['ctools'] = array('#value' => t('You must install the <a href="@ctools-drupal-project">CTools</a> module in order to import a flag.', array('@ctools-drupal-project' => url('http://drupal.org/project/ctools'))));
+  }
+  else {
+    $form['import'] = array(
+      '#title' => t('Import flag'),
+      '#type' => 'textarea',
+      '#default_value' => '',
+      '#rows' => 15,
+      '#required' => TRUE,
+    );
+    $form['submit'] = array(
+      '#value' => t('Import'),
+      '#type' => 'submit',
+    );
+  }
+
+  return $form;
+}
+
+/**
+ * Validate handler; Import a flag.
+ */
+function flag_import_flag_validate($form, &$form_state) {
+  ob_start();
+  eval($form_state['values']['import']);
+  ob_end_clean();
+  // Create the flag object.
+  $new_flag = flag_flag::factory_by_content_type($flag->content_type);
+  foreach ($flag as $key => $value) {
+    $new_flag->{$key} = $value;
+  }
+  unset($new_flag->fid);
+  if ($new_flag->validate()) {
+    // save the new flag for the submit handler.
+    $form_state['storage']['flag'] = $new_flag;
+  }
+}
+
+/**
+ * Submit handler; Import a flag.
+ */
+function flag_import_flag_submit($form, $form_state) {
+  $flag = $form_state['storage']['flag'];
+  // Prepare the flag to be saved.
+  $flag->roles = explode(',', $flag->roles);
+  $flag->options = unserialize($flag->options);
+  foreach ($flag->options as $key => $value) {
+    $flag->{$key} = $flag->options[$key];
+  }
+  $flag->save();
+  if (!$flag->disabled) {
+    $flag->enable();
+  }
+  _flag_clear_cache();
+}
+
+
+/**
+* Export a flag and display it in a form.
+*/
+function flag_export_flag(&$form_state, $flag) {
+  if (!module_exists('ctools')) {
+    $form['ctools'] = array('#value' => t('You must install the <a href="@ctools-drupal-project">CTools</a> module in order to import a flag.', array('@ctools-drupal-project' => url('http://drupal.org/project/ctools'))));
+  }
+  else {
+    $obj = flag_ctools_load_flag($flag->name);
+    drupal_set_title(check_plain($obj->title));
+    $code = flag_ctools_export_flag($obj, $flag);    
+    // Link to the features admin if module is present, or to the drupal project
+    // page.
+    $features_link = module_exists('features') ? url('admin/build/features') : url('http://drupal.org/project/features');
+
+    $form['export'] = array(
+      '#type' => 'textarea',
+      '#title' => t('Export flag'),
+      '#description' => t('Use the exported code to later <a href="@import-flag">import</a> it, or use the <a href="@features-drupal-project">Features</a> module to pack your flags in code.', array('@import-flag' => url('admin/build/flags/import'), '@features-drupal-project' => $features_link)),
+      '#value' => $code,
+      '#rows' => 15,
+    );
+  }
+  return $form;
+}
+
+/**
+* Load a single flag.
+*/
+function flag_ctools_load_flag($name) {
+  ctools_include('export');
+  $result = ctools_export_load_object('flags', 'names', array($name));
+  if (isset($result[$name])) {
+    return $result[$name];
+  }
+}
+
+/**
+* Export a flag.
+*
+* @param $obj
+*   The CTools object.
+* @param $flag
+*   The flag object.
+*
+*/
+function flag_ctools_export_flag($obj, $flag, $indent = '') {
+  ctools_include('export');
+  $output = ctools_export_object('flags', $obj, $indent);
+
+  // Add flag sub-types, as it exists in a different table, and we don't
+  // register it in ctools.
+  $output .= '$flag->types = '. ctools_var_export($flag->types) .";\n";
+  return $output;
+}
