Download & Extend

E_ALL Compliance for the CA Module

Project:Ubercart
Version:6.x-2.x-dev
Component:Code
Category:task
Priority:normal
Assigned:AlexisWilke
Status:closed (duplicate)

Issue Summary

This is the initial pass for EALL Compliance in the CA module. No logic changed, just error checking.

AttachmentSizeStatusTest resultOperations
eall_ca.module.patch28.16 KBIgnored: Check issue status.NoneNone

Comments

#1

Fixed a spacing error. Use the new patch ryan.

AttachmentSizeStatusTest resultOperations
eall_ca.module.patch28.16 KBIgnored: Check issue status.NoneNone

#2

Status:needs review» needs work

I've set my test site to report E_ALL, and I don't see any notices on any of those pages. In fact, the only error I see is caused by a missing trigger on a custom predicate because I had reverted a change that had added one earlier.

I think E_ALL compliance is important, but I don't think this patch gets us any closer.

#3

E_ALL has different values for various versions of PHP. Likewise, E_STRICT is not included in E_ALL and applies only for PHP 5. So as part of your examination of these issues for Ubercart, perhaps we should start with a clear statement of what minimum version of PHP Ubercart will support - right now it's been left pretty fuzzy ... I'm all for requiring PHP 5.2 or above, regardless of whether Drupal pretends to support PHP 4. I don't see that "E_ALL" compliance has any meaning unless it's tied to a definite version of PHP.

I think it's important to give the code a cleansing, although this is mainly necessary because of shortcomings in the PHP language. I also think the issue of E_ALL in Drupal coding standards http://drupal.org/node/34341 needs to be worked on, because there's a lot of ambiguity in the current proposal.

#4

As I go through the code, I am finding it more and more cumbersome to ensure E_ALL compliance. At some points, I take a leap of faith hoping that the calling function has already verified the data. This compliance was run on PHP 5.2 on MAMP. Other versions might not work.

#5

Good points raised by TR. At this point, for UC 2, I think we were settling on PHP 5.2 b/c of our ImageCache dependence for OOB image support. I'll need Lyle to corroborate, though, because I suppose we never wrote it anywhere. Our .info files do state PHP 5.0 at the very least.

Also, a couple things to keep in mind when making code compliant:

  1. Constants should be capitalized, therefore null should be NULL. See the naming conventions at http://drupal.org/coding-standards.
  2. When variables are declared at the beginning of functions, introduce a blank line after them so there's separation between variable declaration and the meat of the function. This patch does this in some places it seems but not in others.
  3. Take into consideration whether or not existing APIs will ensure that variables are set. For example, many of the lines in this patch are devoted to making sure the various keys exist in things like $predicate arrays. The API function ca_predicate_load() will make sure that these keys exist by virtue of how it's building the predicate array. Someone could write a module that didn't conform to the API specifications, so maybe I'm understanding this point wrong, but I don't think Drupal generally panders to people who use APIs improperly. (An example would be the t() function which doesn't do validation to ensure the second argument is an array.) If it results in a bunch of extra code and inline if statements, I'd rather not pander to them either.

Feedback from anyone?

#6

Drupal 7 will require PHP 5.2, so requiring it now will make updating the code that much easier. I thought we'd mentioned somewhere that we were only going to require 5.0, even though we're developing with 5.2.

I'm not particularly concerned about E_STRICT compliance. Part of the reason is that I have Devel set up to use Krumo for its backtrace messages, and it is not at all E_STRICT. This leads to a cascading infinite recursion of notices that crash my site. Hopefully this will be fixed by the time PHP 6 is done and E_ALL includes E_STRICT.

I agree with Ryan's 3rd point. Anyone who doesn't use an API correctly deserves the errors they get. Otherwise, they wouldn't necessarily know they are using it incorrectly. However, that does mean that we should build an API that is easy to use correctly and doesn't have errors when that happens.

#7

OK, now I have to apologize, because I figured out why I wasn't seeing any E_NOTICEs. I had set the drupal_error_handler() to use E_ALL, but the backtrace_error_handler() in devel.module was still set to E_ALL ^ E_NOTICE. So, yes, ca.admin.inc needs fixing.

#8

Status:needs work» needs review

Unless this patch is causing errors, could we commit it? It will take several patches on the same files to bring ubercart to EALL Compliance. This is something that will take some time since the dataset is continually changing.

#9

Status:needs review» needs work

The patch may not cause errors, but it needs to be rerolled to address my points in #5.

#10

Tagging

#11

I just found a couple of E_ALL errors (notices) and wanted to share... I see that someone already got a few fixes here.

In regard to using NULL instead of null and other such things, you probably want to use the coder project to check your code before submitting.

I'm submitting my patch because I did not see the same things fixed in the other patch...

Thank you.
Alexis

AttachmentSizeStatusTest resultOperations
ubercart-e_notices3-6.x.patch1.42 KBIgnored: Check issue status.NoneNone

#12

Could we have some form of a procedure to submit E_NOTICE patches and make sure they get applied?

I'm updating my version and most of the code that I have to copy & paste from my existing version are E_NOTICE error related code. That's annoying since in most cases it's just a small change that fixes the use of a variable...

I have submitted many that you did apply, but others get left behind like those here.

And I have a tons more to submit (actually you should run your code with E_ALL and fix many yourselves! but oh well...)

Thank you.
Alexis Wilke

#13

@AlexisWilke: This issue is still listed as "needs work". If you can fix up the previous patch from #1 to address the issues in #5 and to add your additional fixes from #11, then it will be ready for review. Then all we will need is someone to give it a good test to make sure it addresses all the E_ALL issues in the CA module. So far, it doesn't seem that anyone has interest enough in this issue to do that work.

I'm not too keen on having to process dozens of E_ALL patches. I would rather have one big one which takes care of all the issues, excepting only those changes which are non-trivial. That's why I went through the issue queue three months ago and tagged the E_ALL issues. As I've said in other threads, if you're willing to do the work to roll the patches, address any concerns, and get the patches reviewed, I'm willing to commit your patches.

#14

TR,

Okay, I'm close... I will probably post a new patch in a few days.

Patch in #1 has many mistakes (i.e. conditions that are negated) and changed things that had nothing to do with E_ALL (like adding t() in menu items, which, as we know, is wrong.) Also some of the changes are not necessary (i.e. I do not get any E_NOTICE in those places...) but that could be because I don't have the exact same version of PHP. (I use PHP 5.2.4-2ubuntu5.10 on my test server)

More soon,
Alexis

#15

Assigned to:thenorman» AlexisWilke
Status:needs work» needs review

Hi TR,

There is a patch. It's only 12,000 lines, about 47Kb.

I always follow the Drupal coding rules so this will look correct as requested by #5.

Also, I very much agree with point (3) of #5, it is important to NOT avoid E_NOTICE errors of invalid data. If someone does not define the title or name of something when that parameter is mandatory, the E_NOTICE will appear. Much better!

I ran Coder against the files I'm patching so a few of the changes are Coder changes and not directly E_ALL related. Coder formatting is just a few spaces added/removed.

Thank you.
Alexis

AttachmentSizeStatusTest resultOperations
ubercart-2.x-ca_e_notices-6.x.patch47.73 KBIgnored: Check issue status.NoneNone

#16

Hi TR,

Are you making good progress on that last patch I submitted? You said you'd apply it if I were to supply it, and here it is! 8-)

Also, today, I got another set of warnings. I went to the conditional actions page, sorted by trigger and got the following 3 notices:

  • notice: Undefined index: uc_coupon_purchase in /usr/clients/www/drupal/sites/all/modules/ubercart/ca/ca.admin.inc on line 93.
  • notice: Undefined index: get_quote_from_ups in /usr/clients/www/drupal/sites/all/modules/ubercart/ca/ca.admin.inc on line 93.
  • notice: Undefined index: get_quote_from_usps_intl_env in /usr/clients/www/drupal/sites/all/modules/ubercart/ca/ca.admin.inc on line 93.

In itself, it does not look too bad, except that I removed those 3 modules... so I would think that they should not be referenced anymore once removed (disabled + uninstalled, but even just disabled!)

Thank you.
Alexis

#17

TR,

As I was making an update and going through all the changes I made to keep them... I wanted to underline the following which is a bug. So I'm posting here again to push this issue back to the top since E_ALL does help you in fixing real bugs. I hope you'll have the time to look into it.

Thank you.
Alexis

<?php
@@ -239,17 +243,21 @@
  
$save = FALSE;

  
// Load the original predicate.
-  if ($form_state['values']['pid'] !== 0) {
+  if (
$form_state['values']['predicate_pid']) {
    
$predicate = ca_load_predicate($form_state['values']['predicate_pid']);
+   
// in case the load fails, save the #pid in the array
    
$predicate['#pid'] = $form_state['values']['predicate_pid'];
   }
+  else {
+   
$predicate = array();
+  }
?>

#18

Hi TR,

What would you propose so we get the patch in #15 reviewed? Do you have the time to do it? This includes all the CA problems I have seen. Not all the E_ALL problems of Übercart though...

On my end, I have used those changes for a while one a couple of sites (one being live) and found no side effects. So I'd feel like marking reviewed but since I'm the author... 8-)

Thank you.
Alexis

#19

Here is a review, just to checking for anything that stood out while reading through the patch, I haven't actually applied or tested it.

+++ ubercart/ca/ca.admin.inc 2010-06-06 15:54:04.000000000 -0700
@@ -239,17 +243,21 @@
-  if ($form_state['values']['pid'] !== 0) {
+  if ($form_state['values']['predicate_pid']) {

Why is the key changed here, is this some other bug?

+++ ubercart/ca/ca.admin.inc 2010-06-06 15:54:04.000000000 -0700
@@ -537,7 +556,7 @@
-      '#argument_map' => $value['argument_map'],
+      '#argument_map' => isset($value['argument_map']) ? $value['argument_map'] : NULL,

Doesn't seem to make much sense checking for NULL, only to just set it NULL if it is NULL

+++ ubercart/ca/ca.admin.inc 2010-06-06 15:54:04.000000000 -0700
@@ -803,9 +824,9 @@
-      '#default_value' => $condition['#argument_map'][$key],
+      '#default_value' => isset($condition['#argument_map'][$key]) ? $condition['#argument_map'][$key] : NULL,

NULL?

+++ ubercart/ca/ca.admin.inc 2010-06-06 15:54:04.000000000 -0700
@@ -1012,23 +1033,23 @@
-          '#argument_map' => $cond_value['argument_map'],
+          '#argument_map' => isset($cond_value['argument_map']) ? $cond_value['argument_map'] : NULL,

NULL?

+++ ubercart/ca/ca.ca.inc 2010-06-06 13:44:42.000000000 -0700
@@ -150,14 +152,14 @@
-    '#default_value' => $settings['date'],
+    '#default_value' => empty($settings['date']) ? NULL /* = time() */ : $settings['date'],

What is this: NULL /* = time() */

+++ ubercart/ca/ca.install 2010-06-02 23:26:33.000000000 -0700
@@ -18,7 +18,7 @@
-        'default' => '',
+        //'default' => '', -- primary keys should never have a default

Does this change also require an update as well? No need to leave this line in with that comment, should just remove the line.

+++ ubercart/ca/ca.module 2010-06-06 14:36:14.000000000 -0700
@@ -259,12 +260,7 @@
     // Unset the predicate if it doesn't use the specified trigger.
-    if ($value['#trigger'] != $trigger) {
-      unset($predicates[$key]);
-      continue;
-    }
-
-    if (!$all && $value['#status'] <= 0) {
+    if ($value['#trigger'] != $trigger || (!$all && $value['#status'] <= 0)) {

The problem with consolidating all this logic is trying to read it - some extra comments might help here. Also you are removing the unset() which is effecting the logic in this function.

+++ ubercart/shipping/uc_ups/uc_ups.module 2010-06-06 16:00:27.000000000 -0700
@@ -71,6 +71,26 @@
/**
+ * Get the quote enabled settings.
+ */
+function uc_ups_get_quote_enabled() {
+  return variable_get('uc_quote_enabled', array())
+    + array(
+      'ups' => 0,
+    );
+}
+
+/**
+ * Get the quote method weight.
+ */
+function uc_ups_get_quote_method_weight() {
+  return variable_get('uc_quote_method_weight', array())
+    + array(
+      'ups' => 0
+    );
+}
+

This doesn't feel quite right... is there not a way to ensure the variables contains the correct contents to start with?

+++ ubercart/shipping/uc_usps/uc_usps.module 2010-06-06 15:41:50.000000000 -0700
@@ -41,6 +41,32 @@
/**
+ * Get the quote enabled settings.
+ */
+function uc_usps_get_quote_enabled() {
+  return variable_get('uc_quote_enabled', array())
+    + array(
+      'usps' => 0,
+      'usps_env' => 0,
+      'usps_intl' => 0,
+      'usps_intl_env' => 0,
+    );
+}
+
+/**
+ * Get the quote method weight.
+ */
+function uc_usps_get_quote_method_weight() {
+  return variable_get('uc_quote_method_weight', array())
+    + array(
+      'usps' => 0,
+      'usps_env' => 0,
+      'usps_intl' => 1,
+      'usps_intl_env' => 1,
+    );
+}
+

Same as above.

+++ ubercart/uc_attribute/uc_attribute.ca.inc 2010-06-06 16:29:01.000000000 -0700
@@ -85,7 +85,7 @@
-    '#default_value' => $settings['attribute_option'],
+    '#default_value' => isset($settings['attribute_option']) ? $settings['attribute_option'] : NULL,

NULL again.

+++ ubercart/uc_cart/uc_cart.ca.inc 2010-06-04 03:45:55.000000000 -0700
@@ -154,7 +154,7 @@
-    '#default_value' => $settings['class'],
+    '#default_value' => isset($settings['class']) ? $settings['class'] : NULL,

NULL

+++ ubercart/uc_order/uc_order.module 2010-05-31 16:51:41.000000000 -0700
@@ -1175,6 +1175,9 @@
   if (!$admin) {
     $join = " LEFT JOIN {uc_order_statuses} AS os ON oc.order_status = os.order_status_id";
   }
+  else {
+    $join = "";
+  }

I personally prefer something like this written as:

<?php
$join
= "";
if (!
$admin) {
 
$join = " LEFT JOIN {uc_order_statuses} AS os ON oc.order_status = os.order_status_id";
}
// or an alternative one line way would be
$join = empty($admin) ? "" : " LEFT JOIN {uc_order_statuses} AS os ON oc.order_status = os.order_status_id";
?>

For two reasons, less lines of code and it just feels better to define the variables outside the if context when the intension is to use it outside that context.

There are a lot of lines which have the format of " = isset(something) ? something : NULL;", whats the difference between just saying "= something" (this could be some quirk of PHP I'm not aware of?). If the effort is taken to check all these values, then why not give it a meaningful default then just NULL?

Also just to clarify, none or very few of these may need changing, all I have done is make some comments against changes to try and understand things that are not obvious.

Powered by Dreditor.

#20

Title:EALL Compliance for the CA Module» E_ALL Compliance for the CA Module

univate,

Thank you for taking the time to review the patch.

This issue is about E_ALL errors which I guess you have turned off in your setup, otherwise you'd been fixing them like crazy! 8-) You get tons of them all over the place with Übertcart.

The isset() and empty() functions check whether a variable is at all set. They both return TRUE if the variable is set to NULL though, but there is still a difference because, when not set at all, a variable returns NULL (which may be transformed to 0 in some environment when a number is used) but it generates an E_NOTICE. But the use of NULL is to avoid changing the behavior, using NULL is very safe (i.e. very close to not changing the code.)

So, in the following, when the variable (array at given index) is not set the 1st line generates an E_NOTICE error, the 2nd does not. The 2nd line does the same thing though and sets the value to NULL as the 1st does when the variable is not set. If you have a better default, be my guest and change the NULL with what you expect in the argument map value entry (empty array?)

<?php
     
'#argument_map' => $value['argument_map'],
     
'#argument_map' => isset($value['argument_map']) ? $value['argument_map'] : NULL,
?>

+++ ubercart/ca/ca.admin.inc 2010-06-06 15:54:04.000000000 -0700
@@ -239,17 +243,21 @@
-  if ($form_state['values']['pid'] !== 0) {
+  if ($form_state['values']['predicate_pid']) {

I talk about it in #17. The 'pid' index is not defined and thus I get an E_NOTICE here (which is why any PHP programmer should have E_NOTICE turned on!) If you look at the code of the function you will see that 'pid' is never used, however, you use the 'predicate_pid'.

The problem, and the reason for talking about it in #17 is that changing that test will change the behavior. Before, the if() was always getting TRUE, not matter what, because 'pid' index being undefined it could never ever be set to 0. In other words, by fixing the if() you will now skip the if() block and that may not be correct... (even if it were the intend!)

+++ ubercart/ca/ca.install 2010-06-02 23:26:33.000000000 -0700
@@ -18,7 +18,7 @@
-        'default' => '',
+        //'default' => '', -- primary keys should never have a default

For cleanliness, it would indeed be a good idea to remove the default from the existing tables. As mentioned in another issue post, this can cause problems with MySQL (PostgreSQL ignores the value properly.) And yes, we can just delete the line. It was to make sure that you'd understand why it shouldn't be there.

+++ ubercart/ca/ca.module 2010-06-06 14:36:14.000000000 -0700
@@ -259,12 +260,7 @@
     // Unset the predicate if it doesn't use the specified trigger.
-    if ($value['#trigger'] != $trigger) {
-      unset($predicates[$key]);
-      continue;
-    }
-
-    if (!$all && $value['#status'] <= 0) {
+    if ($value['#trigger'] != $trigger || (!$all && $value['#status'] <= 0)) {

In this one, the unset() is still there. You are doing it twice. In regard to making it an easy read, it seems better to avoid the continue, but we could also use one extra else as in:

<?php
   
if ($value['#trigger'] != $trigger) {
      unset(
$predicates[$key]);
     
//continue; -- remove that
   
}
    elseif (!
$all && $value['#status'] <= 0) {
      unset(
$predicates[$key]);
?>

And then it looks like two if() that do the exact same thing... hence the simplification I proposed.

+++ ubercart/shipping/uc_ups/uc_ups.module 2010-06-06 16:00:27.000000000 -0700
@@ -71,6 +71,26 @@
/**
+ * Get the quote enabled settings.
+ */
+function uc_ups_get_quote_enabled() {
+  return variable_get('uc_quote_enabled', array())
+    + array(
+      'ups' => 0,
+    );
+}

This one has the advantage to fixing existing and future installations. Putting the 'ups' => 0 inside the array() default value only works for new installations.

Again, this is for E_NOTICEs and is not otherwise required since NULL is viewed as 0 when a number is required.

Let me know if that answers all your questions. Depending on your answer, I'll provide a better patch. 8-)

Thank you.
Alexis Wilke

#21

Status:needs review» needs work

Alexis, I understand this is about E_ALL which is exactly why I was specifically looking for any places where you potentially change the logic and not just fix an E_NOTICE. As I said I didn't apply or test the functionality of the patch and I didn't write any of this code myself, all I have done was provided a review of the contents of the patch to help you move the issue forward - I would suggest that you can stop the condescending comments like "(which is why any PHP programmer should have E_NOTICE turned on!)", its starting to get old with all the different issues you have posted this and I will get tied as I'm sure other will of bothering to help with this issue. Lets just keep the issue on topic and fix it.

I'll admit I didn't have the comments from #17 in my mind when reviewing the code, so my first issue is no logger a problem as you have explained that - although you could make this issue easier to fix by separating any bug fixes you find in their own issues as this is supposed to be focussed on E_ALL compliance (I understand you found the issue due to E_ALL, but its not an E_ALL problem that is a logic error where an index is being used that doesn't exist). By committing this patch as is there will continue to be questions about whether that change will break something else and that change might also get better exposure with its own issue.

The NULL lines probably comes from my background as a C programmer where having variables undefined (NULL) is a potential memory leak issue, so I personally don't think NULL should be used as a valid value set by any variables (isn't that also going to be a potential issue for throwing other E_NOTICE messages elsewhere?), its just not the best programming practice in my mind to leave variables undefined - if this is going to be fixed, then we may as well apply a fix thats not going to possibly throw more E_NOTICE's. The bigger thats causing these errors is really the poor typing in PHP.

I guess the issue I see with those array merges in uc_ups is those operations are done every time you require those variables - and array merging is not a cheap operation in most programming language (to be honest I have not investigated if PHP has some efficient way that other languages don't), but my thought is would it not be better to add the values to the variable on installation and also provide an update to add those values for any sites that don't have them set. I'm sure doing it that way will also have a small performance benefit over the current proposed patch.

#22

univate,

The thing is that in some places, NULL is the only way to obtain the right behavior here.

The one with time() would otherwise required a very complex function call, whereas NULL is dead simple. Some others, I tried what I thought would be the right default value but did not get the right result either... When it is just '#value', then '' or 0 work just fine, so I'll make sure that those get fixed.

> "which is why any PHP programmer should have E_NOTICE turned on!"

In that regard, imagine yourself apply my patch each time. It does not work as is... who do you think is most bothered? The one who spends 2h upgrading to the next version of Übercart or the one who reads my comments? And really, I'd be delighted to apply all the easy ones myself if you give me CVS access. Those that I think are "drastic" changes (Adding a function, NULL, + array() and some others, more or less, more than an isset() or an empty()... I would not apply without someone else's review.)

Now, TR said he would take the time to check it if it were in a single patch, but I think that's a lot more scary that way. On the other hand, you and some others did apply many small patches quickly because it is a lot easier to see that it won't hurt anything...

Anyway, my way of thinking is slightly different, I suppose. 8-)

Thank you for the review and I'll submit a new patch with the changes I can make. For the array(), I'll check, and if used each time someone makes a purchase, fixing the variables is a much better idea.

For #17, I posted another issue: #886476: 'predicate_pid' used when 'pid' checked in ca.admin.inc

Thank you.
Alexis Wilke

#23

Status:needs work» closed (duplicate)

I believe most of these PHP notices in ca have been fixed by now. The only way for me to be sure is to have people test, so I'm consolidating all the open PHP notice issues.

#24

TR,

Would you please edit your last post and include a link to the one issue?

Thank you.
Alexis