I know this isn't really of great importance currently, but it has been sitting in the back of my head for while and so I wanted to get rid of it.

I thought about not using drupal_static, but wasn't really sure. From http://api.drupal.org/api/drupal/includes--bootstrap.inc/function/drupal...

In a few cases, a function can have certainty that there is no legitimate use-case for resetting that function's static variable. This is rare, because when writing a function, it's hard to forecast all the situations in which it will be used. A guideline is that if a function's static variable does not depend on any information outside of the function that might change during a single page request, then it's ok to use the "static" keyword instead of the drupal_static() function.

Comments

sun’s picture

+++ libraries.module	11 Jan 2011 19:05:32 -0000
@@ -359,6 +359,11 @@ function libraries_detect_library(&$libr
+  $loaded_libraries = &drupal_static(__FUNCTION__);
+  if (isset($loaded_libraries[$name])) {
+    return FALSE;

Let's squeeze a newline between the static and early return, and also return the statically cached value.

+++ libraries.module	11 Jan 2011 19:05:32 -0000
@@ -377,7 +382,9 @@ function libraries_load($name, $variant 
+  $count = libraries_load_files($library, $variant);
+  $loaded_libraries[$name] = TRUE;
+  return $count;

Let's assign the return value to $loaded_libraries[$name] instead of $count, and also simply return $loaded_libraries[$name] (optionally casted to bool)

Powered by Dreditor.

tstoeckler’s picture

StatusFileSize
new1.88 KB

This adjusts the return value according to #1. I switched the logic around, leading to a bit more indentation, but having the same return statement twice in one function seemed awkward to me.

tstoeckler’s picture

Status: Needs review » Needs work

While reviewing the patch, I just noticed a little weirdness with the current return value, which this patch brings to light.
In short, there is no way to distinguish between an already loaded library and a broken/unloadable library.
Imagine we had #962214: Load library dependencies in and library B depends on library A.
Module X needs library A, so it does

if (libraries_load('library_a')) {
  // Do something.
}

which works well, because libraries_load() returns an integer, which is casted to TRUE, as long as it is not 0.

Now module Y needs library B, so it does

if (libraries_load('library_b')) {
  // Do something.
}

which, because of the dependency calls in turn:

if (libraries_load('library_a')) {
  // Only load library B if library A was loaded.
}

Since library A was already loaded, libraries_load('library_a') will return 0 which will be cast to FALSE, even though it would be fine to load library B.
On the other hand if libraries_load('library_b') doesn't in turn do if (libraries_load('library_a')) { ... } library B will be loaded even is library A is not loaded or even can't be loaded.

Setting to 'needs work' for consideration.

sun’s picture

Since library A was already loaded, libraries_load('library_a') will return 0 which will be cast to FALSE, even though it would be fine to load library B.

This is exactly what I meant at the end of #1, we need to store and return the first/last return value (optionally casted to Boolean, or not).

+++ libraries.module	12 Jan 2011 10:35:03 -0000
@@ -359,25 +359,31 @@ function libraries_detect_library(&$libr
+  $loaded_libraries = &drupal_static(__FUNCTION__);

Needs to default to an array, otherwise $loaded_libraries might now always be an array.

+++ libraries.module	12 Jan 2011 10:35:03 -0000
@@ -359,25 +359,31 @@ function libraries_detect_library(&$libr
+    if (!$library['installed']) {
       return FALSE;
     }
...
+      if (!$library['variants'][$variant]['installed']) {
+        return FALSE;
+      }

Let's not early return here - instead, assign the already figured out value (FALSE) to the static cache and return that instead at the end of the function.

+++ libraries.module	12 Jan 2011 10:35:03 -0000
@@ -359,25 +359,31 @@ function libraries_detect_library(&$libr
+    $loaded_libraries[$name] = libraries_load_files($library, $variant);

This should be wrapped in a check for FALSE then.

Powered by Dreditor.

tstoeckler’s picture

Ahh, now I get it...
That's pretty smart, using the static cache to store the return value, I hadn't thought of that. :)

tstoeckler’s picture

Status: Needs work » Needs review
StatusFileSize
new2.07 KB

Maybe something like this?

tstoeckler’s picture

StatusFileSize
new2.09 KB

And without whitespace.

sun’s picture

+++ libraries.module	15 Jan 2011 14:29:01 -0000
@@ -346,25 +346,37 @@ function libraries_detect_library(&$libr
+  $loaded_libraries = &drupal_static(__FUNCTION__);
...
+  if (empty($loaded_libraries)) {
+    $loaded_libraries = array();
   }

The second argument to drupal_static() specifies the default value; just move the array() in there.

+++ libraries.module	15 Jan 2011 14:29:01 -0000
@@ -346,25 +346,37 @@ function libraries_detect_library(&$libr
+    if (!$library['installed']) {
+      $loaded_libraries[$name] = FALSE;
+    }
...
+    if (!empty($variant) && !empty($library['variants'][$variant])) {
...
+      if (!$library['variants'][$variant]['installed']) {
+        $loaded_libraries[$name] = FALSE;
+      }
+      $library = array_merge($library, $library['variants'][$variant]);
+    }
+
+    if ($loaded_libraries[$name] != FALSE) {
+      $loaded_libraries[$name] = libraries_load_files($library, $variant);
     }

1) Let's initialize $loaded_libraries[$name] with FALSE early, and afterwards, negate the first if condition.

2) Let's turn the second if into an elseif, and drop the last if condition.

3) All of the !empty() in the second condition should bet isset().

4) I think the second condition should only check whether a variant name was passed, and regardless of whether it exists or not, we process it. In turn, the third condition should be sufficient when checking for !empty(variant][installed).

Powered by Dreditor.

sun’s picture

StatusFileSize
new2.49 KB

Helping you out a bit here ;)

tstoeckler’s picture

Status: Needs review » Needs work

That's pretty sweet. I didn't know "+=" works multi-dimensionally.
Only some minor nitpicks below.
Also, if you can think of some way to test this, do tell me, because I couldn't think of one.

+++ libraries.module	15 Jan 2011 15:12:54 -0000
@@ -343,28 +343,41 @@ function libraries_detect_library(&$libr
+ *   An associative array describing the loaded library, containing:

I think it would be good to state that the mentioned keys are additional to the normal ones, something like:
"An array of library information as returned from libraries_info(), containing additionally: ..."

+++ libraries.module	15 Jan 2011 15:12:54 -0000
@@ -343,28 +343,41 @@ function libraries_detect_library(&$libr
+ *   - installed: Whether the library is installed.

Since we are adding this libraries_detect_library() maybe it makes sense to document it there.

+++ libraries.module	15 Jan 2011 15:12:54 -0000
@@ -343,28 +343,41 @@ function libraries_detect_library(&$libr
+      $loaded_files = libraries_load_files($library);
+      $library['loaded'] = $loaded_files;

I sense there is some point to splitting that up into 2 lines, but I don't get it.

Powered by Dreditor.

sun’s picture

Status: Needs work » Needs review
StatusFileSize
new2.8 KB

I didn't know "+=" works multi-dimensionally.

It doesn't ;) The operator adds each key of the right-hand array to the left-hand array, if the array key does not exist yet. In case it doesn't exist yet, the entire corresponding value of the right-hand array is taken over. Note that a left-hand array key with value NULL is also considered to exist; i.e., the operator basically uses array_key_exists(), not isset().

In this case, we merely need to ensure that there is a $variant key. That is, because if there is already a $variant key, then 'installed' is guaranteed to exist on it, too. Only if the $variant key does not exist, we need to ensure that it exists, so the subsequent array_merge() doesn't fail.

Clarified the rest. :)

tstoeckler’s picture

Status: Needs review » Reviewed & tested by the community

Right. I didn't have in mind, that 'installed' is always initialized if the variant is.

Thanks, the code is really slick, now!

sun’s picture

Status: Reviewed & tested by the community » Fixed

Thanks for reporting, reviewing, and testing! Committed to HEAD.

A new development snapshot will be available within the next 12 hours. This improvement will be available in the next official release.

Status: Fixed » Closed (fixed)

Automatically closed -- issue fixed for 2 weeks with no activity.