From 367e5ab78bcb4282ae44258786d0abc7fa6977a1 Mon Sep 17 00:00:00 2001
From: Glenn Pratt <glennpratt@gmail.com>
Date: Sat, 11 Jun 2011 11:18:01 -0500
Subject: [PATCH] #1165158: rfay, mikejoconnor, glennpratt. Check Commerce for entities missing fields in Status report.  Also, add a form for repairing the entity fields.

---
 commerce.admin.inc                          |   62 +++++++++++++++++++++++++++
 commerce.install                            |   44 +++++++++++++++++++
 commerce.module                             |   26 +++++++++++
 modules/customer/commerce_customer.module   |   30 +++++++++++--
 modules/line_item/commerce_line_item.module |   29 ++++++++++++-
 modules/order/commerce_order.module         |   23 +++++++++-
 modules/product/commerce_product.module     |   21 +++++++++
 7 files changed, 228 insertions(+), 7 deletions(-)
 create mode 100644 commerce.admin.inc

diff --git a/commerce.admin.inc b/commerce.admin.inc
new file mode 100644
index 0000000..3e136ee
--- /dev/null
+++ b/commerce.admin.inc
@@ -0,0 +1,62 @@
+<?php
+
+/**
+ * @file
+ * Administration pages for Commerce module.
+ */
+
+/**
+ * Form builder; Form for rebuilding Commerce entity fields.
+ *
+ * @ingroup forms
+ */
+function commerce_admin_field_rebuild_form($form, &$form_state) {
+
+  $header = array(
+    'entity_name' => array('data' => t('Entity name')),
+    'state' => array('data' => t('State')),
+  );
+
+  $options = array();
+  $commerce_entities = array_filter(entity_get_info(), '_is_commerce_entity');
+  foreach ($commerce_entities as $entity_name => $entity_info) {
+    $options[$entity_name] = array(
+      'entity_name' => $entity_name,
+      'state' => t('Default'),
+    );
+    foreach ($entity_info['commerce default fields'] as $field_name => $callback){
+      $field = field_info_field($field_name);
+      if (!in_array($entity_name, $field['entity_types'])) {
+        $options[$entity_name]['state'] = t('Missing fields');
+      }
+    }
+  }
+
+  $form['entities'] = array(
+    '#type' => 'tableselect',
+    '#header' => $header,
+    '#options' => $options,
+    '#empty' => t('No people available.'),
+  );
+
+  $form['submit'] = array(
+    '#type' => 'submit',
+    '#value' => t('Repair selected types'),
+  );
+
+  return $form;
+}
+
+/**
+ * Submit handler for reparing Commerce entity types.
+ */
+function commerce_admin_field_rebuild_form_submit($form, &$form_state) {
+  $entities_to_repair = array_filter($form_state['values']['entities']);
+  foreach ($entities_to_repair as $entity_name) {
+    $entity = entity_get_info($entity_name);
+    foreach ($entity['commerce default fields'] as $field_name => $callback){
+      // Execute field repair callback.
+      drupal_set_message(t('Attempted to repair entity %entity_name field %field_name.', array('%entity_name' => $entity_name, '%field_name' => $field_name)));
+    }
+  }
+}
diff --git a/commerce.install b/commerce.install
index 76aeec6..0326dd4 100644
--- a/commerce.install
+++ b/commerce.install
@@ -1,6 +1,11 @@
 <?php
 
 /**
+ * @file
+ * Install, Update, Requirements functions for Commerce module.
+ */
+
+/**
  * Update Rules to use new prefixed parameter names and tokens.
  */
 function commerce_update_7100() {
@@ -266,3 +271,42 @@ function commerce_update_rename_permissions($map) {
     }
   }
 }
+
+/**
+ * Implements hook_requirements().
+ *
+ * Check the status of commerce fields.
+ */
+function commerce_requirements($phase) {
+  $requirements = array();
+
+  if ($phase = 'runtime') {
+    $broken_entities = array();
+    $commerce_entities = array_filter(entity_get_info(), '_is_commerce_entity');
+    foreach ($commerce_entities as $entity_name => $entity_info) {
+      foreach ($entity_info['commerce default fields'] as $field_name => $callback){
+        $field = field_info_field($field_name);
+        if (!in_array($entity_name, $field['entity_types'])) {
+          $broken_entities[$entity_name] = $entity_name;
+        }
+      }
+    }
+
+    // Don't clutter the Status Report page with nothing to report
+    if (!empty($broken_entities)) {
+
+      $description = 'These entities are missing default fields:';
+      $description .= theme('item_list', array('items' => $broken_entities));
+      $description .= l(t('Rebuild commerce fields'), 'admin/commerce/config/rebuild');
+
+      $requirements['commerce_products_missing_fields'] = array(
+        'title' => t('Commerce fields'),
+        'value' => t('Default fields are missing'),
+        'description' => $description,
+        'severity' => REQUIREMENT_ERROR,
+      );
+    }
+  }
+
+  return $requirements;
+}
diff --git a/commerce.module b/commerce.module
index aa3df88..6020d15 100644
--- a/commerce.module
+++ b/commerce.module
@@ -38,6 +38,25 @@ function commerce_hook_info() {
 }
 
 /**
+ * Implements hook_menu();
+ */
+function commerce_menu() {
+  $items = array();
+
+  $items['admin/commerce/config/rebuild'] = array(
+    'title' => 'Repair Commerce Fields',
+    'description' => 'Rebuild default commerce entity fields.',
+    'page callback' => 'drupal_get_form',
+    'page arguments' => array('commerce_admin_field_rebuild_form'),
+    'access arguments' => array('configure store'),
+    'type' => MENU_CALLBACK,
+    'file' => 'commerce.admin.inc',
+  );
+
+  return $items;
+}
+
+/**
  * Finds all fields of a particular field type.
  *
  * @param $field_type
@@ -761,3 +780,10 @@ function commerce_entity_access_query_alter($query, $entity_type, $base_table =
     $query->where('1 = 0');
   }
 }
+
+/**
+ * Array filter callback to test whether an entity belongs to a commerce module.
+ */
+function _is_commerce_entity($entity_info) {
+  return isset($entity_info['commerce default fields']);
+}
diff --git a/modules/customer/commerce_customer.module b/modules/customer/commerce_customer.module
index 99fc485..a1ffd65 100644
--- a/modules/customer/commerce_customer.module
+++ b/modules/customer/commerce_customer.module
@@ -46,6 +46,9 @@ function commerce_customer_entity_info() {
         'user key' => 'uid',
         'access tag' => 'commerce_customer_profile_access',
       ),
+      'commerce default fields' => array(
+        'commerce_customer_billing' => 'commerce_customer_configure_customer_types',
+      ),
     ),
   );
 
@@ -108,16 +111,35 @@ function commerce_customer_hook_info() {
  * Implements hook_enable().
  */
 function commerce_customer_enable() {
-  // Add the address field to customer profile bundles.
-  foreach (commerce_customer_profile_types() as $type => $profile_type) {
-    commerce_customer_configure_customer_profile_type($profile_type);
-  }
+  commerce_customer_configure_customer_types();
 }
 
 /**
+ * Configure types provided by this module.
+ */
+function commerce_customer_configure_customer_types() {
+   // Add the address field to customer profile bundles.
+   foreach (commerce_customer_profile_types() as $type => $profile_type) {
+     commerce_customer_configure_customer_profile_type($profile_type);
+   }
+ }
+/**
  * Implements hook_modules_enabled().
  */
 function commerce_customer_modules_enabled($modules) {
+  commerce_customer_configure_customer_fields($modules);
+}
+
+/**
+ * Configure fields for the customer profile.
+ *
+ * @param $modules
+ *   Array of module names to be acted on.
+ */
+function commerce_customer_configure_customer_fields($modules = NULL) {
+  if (empty($modules)) {
+    $modules = module_implements('commerce_customer_profile_type_info');
+  }
   // Loop through all the enabled modules.
   foreach ($modules as $module) {
     // If the module implements hook_commerce_customer_profile_type_info()...
diff --git a/modules/line_item/commerce_line_item.module b/modules/line_item/commerce_line_item.module
index 8fa8eb3..899a2b1 100644
--- a/modules/line_item/commerce_line_item.module
+++ b/modules/line_item/commerce_line_item.module
@@ -35,6 +35,10 @@ function commerce_line_item_entity_info() {
       'access callback' => 'commerce_line_item_access',
       'metadata controller class' => '',
       'token type' => 'commerce-line-item',
+      'commerce default fields' => array(
+        'commerce_unit_price' => 'commerce_line_item_configure_line_item_fields',
+        'commerce_total' => 'commerce_line_item_configure_line_item_fields',
+      ),
     ),
   );
 
@@ -212,6 +216,20 @@ function commerce_line_item_views_api() {
  * Implements hook_enable().
  */
 function commerce_line_item_enable() {
+  commerce_line_item_configure_line_item_types();
+}
+
+/**
+ * Implements hook_modules_enabled().
+ */
+function commerce_line_item_modules_enabled($modules) {
+  commerce_line_item_configure_line_item_fields($modules);
+}
+
+/**
+ * Configure each of the line item types.
+ */
+function commerce_line_item_configure_line_item_types() {
   // Loop through and configure all the currently defined line item types.
   foreach (commerce_line_item_types() as $line_item_type) {
     commerce_line_item_configure_line_item_type($line_item_type);
@@ -219,9 +237,16 @@ function commerce_line_item_enable() {
 }
 
 /**
- * Implements hook_modules_enabled().
+ * Configure line item fields that other modules may provide.
+ *
+ * @param $modules
+ *   Array of module names. If empty, will process all modules that implement
+ *   hook_commerce_line_type_info().
  */
-function commerce_line_item_modules_enabled($modules) {
+function commerce_line_item_configure_line_item_fields($modules) {
+  if (empty($modules)) {
+    $modules = module_implements('commerce_line_item_type_info');
+  }
   // Reset the line item cache to get the default options and callbacks.
   commerce_line_item_types_reset();
 
diff --git a/modules/order/commerce_order.module b/modules/order/commerce_order.module
index fc2d775..dc0a0a4 100644
--- a/modules/order/commerce_order.module
+++ b/modules/order/commerce_order.module
@@ -50,6 +50,10 @@ function commerce_order_entity_info() {
         'user key' => 'uid',
         'access tag' => 'commerce_order_access',
       ),
+      'commerce default fields' => array(
+        'commerce_line_items' => 'commerce_order_configure_order_fields',
+        'commerce_order_total' => 'commerce_order_configure_order_fields',
+      ),
     ),
   );
 
@@ -124,7 +128,24 @@ function commerce_order_enable() {
  * Implements hook_modules_enabled().
  */
 function commerce_order_modules_enabled($modules) {
-  // Loop through all the enabled modules.
+  commerce_order_configure_order_fields($modules);
+}
+
+/**
+ * Menu callback to rebuild order fields.
+ */
+function commerce_order_repair_order_fields() {
+  commerce_order_configure_order_type();
+  commerce_order_configure_order_fields();
+  watchdog('commerce_order', 'Rebuilt all order fields');
+  drupal_set_message(t('All order fields have been reconfigured'));
+  return array('#markup' => t('All order fields have been reconfigured'));
+}
+
+function commerce_order_configure_order_fields($modules = NULL) {
+  if (empty($modules)) {
+    $modules = module_implements('commerce_customer_profile_type_info');
+  }  // Loop through all the enabled modules.
   foreach ($modules as $module) {
     // If the module implements hook_commerce_customer_profile_type_info()...
     if (module_hook($module, 'commerce_customer_profile_type_info')) {
diff --git a/modules/product/commerce_product.module b/modules/product/commerce_product.module
index 30ff741..102acc2 100644
--- a/modules/product/commerce_product.module
+++ b/modules/product/commerce_product.module
@@ -112,6 +112,9 @@ function commerce_product_entity_info() {
         'user key' => 'uid',
         'access tag' => 'commerce_product_access',
       ),
+      'commerce default fields' => array(
+        'commerce_price' => 'commerce_product_configure_product_types',
+      ),
 
       // Add entity translation support.
       'translation' => array(
@@ -243,6 +246,13 @@ function commerce_product_permission() {
  * Implements hook_enable().
  */
 function commerce_product_enable() {
+  commerce_product_configure_product_types();
+}
+
+/**
+ * Configure the types provided by this module.
+ */
+function commerce_product_configure_product_types() {
   // Loop through and configure all the currently defined product types.
   foreach (commerce_product_types() as $type => $product_type) {
     commerce_product_configure_product_type($type);
@@ -253,6 +263,17 @@ function commerce_product_enable() {
  * Implements hook_modules_enabled().
  */
 function commerce_product_modules_enabled($modules) {
+  commerce_product_configure_product_fields($modules);
+}
+
+/**
+ * Configure the fields on this provided by other modules.
+ */
+function commerce_product_configure_product_fields($modules = NULL) {
+  if (empty($modules)) {
+    $modules = module_implements('commerce_product_type_info');
+  }
+
   // Loop through all the enabled modules.
   foreach ($modules as $module) {
     // If the module implements hook_commerce_product_type_info()...
-- 
1.7.3

