Just upgraded to 7.x-2.3 to check out the new Libraries UI page. One thing I found a bit confusing is the difference between how results are presented on the Status Report versus how they are shown in admin/reports/libraries. In the new Libraries UI, there are items displayed as "not found" even though they are unnecessary.
For modules we have developed, there are numerous situations where a library is optional, and only in use if the developer has made a selection through the UI to use it. A good example of this is the Views Ticker module. There are six possible jQuery ticker libraries that can be installed, but most likely a site is only going to use one or two of them. In hook_requirements, we loop through all possible options to see which are in use, and only display info on the Status Report for the libraries the developer is actually using.
This is different from the Libraries UI page, which lists every possible library by just performing a call to libraries_detect(). Calling libraries_detect causes jQuery ticker libraries to be displayed as "not found" even though there is most likely only one in use.
I understand about wanting to use libraries_detect() since it provides the quickest results, but what about using $requirements from hook_requirements to parse what is actually being returned, and build the list that way? Or are you expecting that individual modules are now supposed to add conditional logic to hook_libraries_info to not return $libraries if they are not needed? I've always assumed this is not the best choice due to caching considerations.
More than anything else needing some guidance here, since the current information being presented in the Libraries UI report is not what we want or expect for our modules. Thanks.
| Comment | File | Size | Author |
|---|---|---|---|
| #19 | 2724925-16-18-interdiff.txt | 3.26 KB | tstoeckler |
| #16 | libraries-admin_page_update-2724925-16.patch | 6.44 KB | sgdev |
| #16 | interdiff-2724925-13-16.txt | 6.21 KB | sgdev |
Comments
Comment #2
sgdev commentedComment #3
tstoecklerYeah, I agree this is somewhat problematic. The problem is that we currently don't have a way to know which libraries are required and which are merely optional.
Do you have any suggestions on how we could improve the wording / labeling? Maybe it makes sense to completely separate installed and uninstalled libraries to make the uninstalled ones less prominent?
Comment #4
sgdev commentedYes, that's a possibility. What about an approach that leverages the information available via
hook_requirements? This isn't perfect, but does provide a bit more context.Please review the attached patch. The code does the following:
1) Separates the current table into two tables: "Active" and "Inactive, unused, and not found".
2) Creates a third table using
hook_requirementsdata to display "Other required libraries not loaded via Libraries API".3) Creates a fourth table including any other library not in the first three tables that exists in 'sites/all/libraries'.
I'm sure there is probably room for improvement with this patch, or use cases for which I'm not aware, but hopefully this is at least a starting point for discussion.
Comment #6
tstoecklerI like the new UI, I think we should pursue that. Retitling to that effect.
Thanks!!!
Some thoughts on the patch:
I agree with changing "Installed version" to "Version". ++
I think it makes sense to keep "Status" for the not-installed table, so let's have separate
$header_installedand$header_errorvariables.Similar to the above, I would suggest
$rows_installedand$rows_error.We should not do that. We should solve this problem properly at some point and allow modules to declare dependencies on libraries. At that point we could implement hook_requirements() for those modules and also display this information in the report, but let's not do it this way around. Please just remove this for now and see you in #1148246: Implement hook_requirements() to list libraries ;-)
Please just use
libraries_get_libraries(), that should be sufficient.Use
if ($library['installed'])instead, it is a boolean.Instead of duplicating it, let's just build up a
$rowvariable once and then either stick it in$rows_installedor in$rows_errordepending on the status.Why is this necessary? Please revert this in case it is not necessary for this patch.
Comment #7
tstoecklerSince were already overhauling this, I also found a couple things which are wrong with the current code (i.e. my fault, not yours ;-)), can you fix them as well, as part of this patch? That would be awesome:
Please wrap 'Homepage' and 'Download' in t().
Those are not proper sentences, please change that to:
Comment #8
sgdev commentedI should have offered more clarity on these. One of the fundamental problems I see with this page is the use of "installed" and "not installed" (or "error').
Really this is not true... as I mentioned with Views Ticker, we have cases where the library is definitely installed correctly, but the page shows them as "Not found". The issue is the module's
$requirementsdo not display the library as being installed or uninstalled unless it is actually in use. I know for a fact that Views Ticker is not the only module that does this.So really the distinction should be something like "Active" and "Inactive, unused, or not found". There's no way for us to tell which of these three is actually the case, because this admin page is using
libraries_detect()rather than the actual rules, which are found inhook_requirements.So the "OK" flag is accurate, but anything other than "OK" cannot be trusted for this page. That's why I separated the error message.
Let me know if this makes sense. Thanks.
Comment #9
tstoecklerHmm... I disagree, to be honest. The library, can - in fact - not be found. The thing is that we currently make it seem as though that were a problem for the site operation. That is the problem, I think. So we should make it seem less like "This is definitely a problem" and rather make it seem like "This might be a problem, but maybe you're doing just fine." I don't know how to do that, specifically, I think the separation is a step towards that, but I think changing the error message is not the right thing.
Comment #10
sgdev commentedI do not think there is any disagreement. Yes, the library can be "not found". It can also be "unused". There is no way for us to know which is the case, other than labeling them as "Inactive, unused, and not found libraries."
As for the error handling, let me explain in more detail. This is the current logic:
If
!file_exists($library['library path'])isTRUE, we know for certain the library is missing. In this case, we can return an error message of'The %library library could not be found.'. This is very straightforward.If
$library['library path'] === FALSE, the situation is ambiguous. ReturningFALSEcould mean that the library is missing, or it could be a situation like Views Ticker, where the library is not being used. So for this case, we return a message of'The %library library is inactive, unused, or could not be found.'. Could be any one of those.The only change in the error is to more accurately present the reason for the message. With Views Ticker there is no error, and saying only "library could not be found" is incorrect.
If I was to offer my preference, I believe the first message should be an error, and the second should be a warning.
This is similar logic for referring to the rows as
$ok_rowand$not_ok_row(or the other way around, as$row_okand$row_not_ok). Calling them "$row_installed" and "$row_error" is fine if that is what you want, but it is inaccurate. The Views Ticker libraries are installed correctly, but are being tagged as "error".I find it difficult to follow code that uses "installed" or "error", when really the distinction we are creating is does it return "ok" or "not ok" (where "not ok" may mean "not found", but could also mean "unused").
I will create the patch however you want, I'm just offering my feedback on why I think using the "installed" / "error" paradigm is not the best option.
Comment #11
tstoecklerHmm... let's see I'm still not quite convinced :-) Specifically this:
This is incorrect. If
$library['library path']is set toFALSEit means thatlibraries_get_path()returnedFALSEwhich is identical to saying that the library could not be found. The only other possibility is that it was set toFALSEupfront which is completely pointless and not supported.Comment #12
sgdev commentedYou are right. I investigated further, and realized I am pointed at a repository that does not have the libraries I expected to be there. Sorry about that!
Comment #13
sgdev commentedHere is an updated patch. Let me know your thoughts on the titles / descriptions, and if any adjustments should be made. Thanks.
Comment #15
tstoecklerYay, I'm glad we're on the same page, now. :-)
The patch looks really close, thanks for sticking with it.
Some comments:
I think we should go with
$libraries_registeredand$libraries_unregisteredand explain the difference in a code comment above that. Something like:That's a little verbose, so feel free to improve on that, but something like that.
Also not 100% sure about "registered" and "unregistered" as variable names, maybe you have better suggestions?
libraries_get_libraries()keys by library name (although apparently that is not properly documented :-() so I think we can drop the entire foreach.I think this deserves a code comment. In fact, it would even be cool to put a comment like "Only show the status libraries with an error." above the declaration of the header variables, and then we can put a comment like "Only show the status for libraries with an error, see above." here. I think that makes it a bit more clear, what is happening.
Because library machine names have to be unique I think we can simplify this to
unset($libraries_registered[$library['machine name']]);I'm not super happy about putting the markup in
#prefixand#suffixespecially the<br>part, but I don't have any suggestion on how to improve that off the top of my head. So if you don't either I would be fine committing it this way, we can always improve in a follow-up. Just wanted to mention that regardless.I would go with "Path" instead of "Location", we call it path everywhere else. Also I think it makes sense to put this declaration up to the top with the other headers. Then we have
$header_installed,$header_errorand$header_unregistered. Having written that, I was thinking whether it would make sense to split those three tables into three different functions, but probably we would have to refactor a bunch of more code, so let's consider that in a follow-up maybe (if at all).Instead of only conditionally outputting the render array for the "unregistered" table, I think it's preferrable to do
I.e. always output the render array for the tables but hide it via
#accessif there are no rows. That way if people alter/extend this render array in some way, they can avoidisset()checks.Again, thanks a lot for sticking with this. I really feel good about this now.
Comment #16
sgdev commentedSee attached update. I don't have a better suggestion for "registered" / "unregistered" at this time.
Removed the
#prefixand#suffixyou mentioned, and just put all code in the#markup. Isn't any better or worse, but maybe you prefer it this way.Comment #19
tstoecklerThanks a lot for the patch!
I went ahead and committed it...
... but I couldn't help myself from adapting the wording and the table heading a bit. I also moved them into the table element itself with a #prefix. (Sorry for going back and forth on that a bit.) I think we should - in a follow-up - create a dedicated theme function that is like theme_table() but also takes a #title and a #description.
I went back to "Installed/Uninstalled/Unregistered" on the table headers. I still think that is more clear. But since I know you have a slightly different view on this marking this "Active" so we can further discuss UI/wording improvements if you want. But now the rest of the restructuring is in 8.x-2.x so further patches should be manageable more easily and I definitely think this is an improvement over previous 8.x-2.x.
If you think the current wording is fine, feel free to mark the issue fixed.
Attached interdiff shows my pre-commit changes.
Comment #21
tstoecklerJust committed a small follow-up that implements such a theme function mentioned in #19.
Still would love to hear your thoughts, @ron_s! :-)
Comment #23
sgdev commentedI understand why you've made the changes, although as you said, I think I have a slightly different view. :-)
This issue is just a simple example of what I see as a general challenge for Drupal. The software is very good at being technically proficient, but creates barriers to entry for less technical developers.
As an example is this Libraries issue I just closed: https://www.drupal.org/node/2741145
What this person is seeking is the UI to incorporate libraries like CKEditor. If I visit Drupal status report, I'll see "CKEditor 4.5.9". However since CKEditor doesn't share metadata, what I see in the Libraries UI page is "ckeditor ... sites/all/libraries/ckeditor".
The average site builder doesn't care about the technical implications of
hook_requirementsdependencies or why CKEditor doesn't provide metadata to Libraries API. All he or she knows is "version 4.5.9" can be seen on Status Report, but not in Libraries UI.This is why I initially added the
$requirements = module_invoke_all('requirements', 'runtime');table. I was attempting to find a middle ground that helps site builders accomplish their goals in the near term, while striving toward longer-term goals. I understand fixinghook_requirementsdependencies is the better approach, but how long do we wait for that to happen (issue originally opened 5+ years ago)? Why don't we try to make incremental improvements rather than waiting for the best technical solution?As for the labeling, I think the terms are too technical and inconsistent with the rest of Drupal. For an average person, what does "registered" mean? What does "uninstalled" mean, especially when the Drupal paradigm is that an uninstalled module is one that has been removed but still exists in the filesystem? I tried to overcome some of that with the originally included descriptions.
I believe "active", "inactive", and "other" are a better representation of these categories, while "installed", "uninstalled", and "unregistered" are less user-friendly. I can try identifying other labels, but I think you are looking for a more technically pure answer. Correct me if I'm wrong.
Comment #24
tstoecklerHmm... OK let's see.
In the case of CKEditor that might just work, but in general this vastly incorrect. There is no defined structure for the keys that come out of
hook_requirements(). They might just match any library machine name, but they also might not, and more importantly some completely different information might be portrayed there that has nothing to do with libraries. Therefore for me this is a complete no-go. I don't see how we can possibly get away with this. I didn't put it in such strong words earlier, because I didn't want to needlessly evoke a conflict, but I feel very strongly that this is incorrect, not only theoretically, but also practically a can of worms that we would be opening.Hmm, I actually disagree with this. I think specifically "installed" is pretty clear, because installing a library is similar to installing a module, specifically for people downloading stuff and FTP-ing it to their server. And registered vs. unregistered I can see being a little unintuitive, but I find "active" and "inactive" to be completely vague. And it's also not really correct. I.e. we have no idea if any library is "active" or not, maybe it's only active on certain pages, or under certain conditions. And maybe it's not being used at all. Again, this is not so much about technical correctness for me, but more about telling the user what is actually happening. And I don't feel that your terminology was doing a significantly better job at that than mine. And mine is consistent with the rest of the code, so I chose that.
Comment #25
tstoecklerHmm.. marking this fixed due to lack of feedback.
Again @ron_s your effort on this and your input is highly appreciated, I hope this issue has not demotivated you from working on Libraries API in the future. If that is the case I sincerely apologize.
Comment #26
sgdev commented@tstoeckler, I'm always motivated, and certainly will contribute patches in the future if I see a need. I'm also very busy at the moment. However, I'm not exactly sure what feedback you are seeking.
I offered my point of view, and you disagree. Are you wanting me to counter your opinion? I don't have much interest in ongoing philosophical discussions... either we reach an agreement that a change is necessary, or we do not. You are quite firm in your point of view, so I'm unsure what else needs to be discussed.
Comment #27
tstoecklerThat's good to hear. Yeah, I think in the scope of this issue there is not much left to say. I just hope to see you in the queue again, the next you encounter an issue with Libraries API ;-) Thanks again!