Implement libraries_library(), so that modules that work with Libraries API can use their libraries (via drupal_add_library()) without having to implement their own hook_library().

/**
 * Implement hook_libraries_info().
 */
function tinymce_libraries_info() {
  $libraries['tinymce'] = array(
    'files' => array(
      'js' => 'tinymce.js',
      'css' => 'tinymce.css',
    ),
  );
}

// Now to add TinyMCE's JS/CSS, you can do the following...
drupal_add_library('libraries', 'tinymce');
$form['myelement']['#attached'][] = array('libraries', 'tinymce');

Comments

tstoeckler’s picture

The problem is that we can only register libraries that are installed. So we would have to detect all libraries in libraries_library(). That would currently be a performance hit, because we only cache libraries_load() currently.
Of course we could cache libraries_detect(), but I don't think that is necessary.
It is neither tested nor documented, but in theory we already support '#attached' anyway. So instead of your example, you can do:

/**
* Implement hook_libraries_info().
*/
function tinymce_libraries_info() {
  $libraries['tinymce'] = array(
    'files' => array(
      'js' => 'tinymce.js',
      'css' => 'tinymce.css',
    ),
  );
}

// Now to add TinyMCE's JS/CSS, you can do the following...
libraries_load('tinymce');
$form['myelement']['#attached']['libraries_load'][] = array('tinymce');
sun’s picture

Status: Active » Postponed

Before attempting to do this, I want to see how generic something like this can be in the first place.

Based on the initial code for http://drupal.org/project/jquery, I somewhat doubt there's anything generic here.

Lastly, (I know I'm repeating myself ;) bear in mind that hook_library() is fundamentally different to Libraries API. The potential overlap with hook_library() only exists for 1:1 library-to-module relationships.

tstoeckler’s picture

Issue summary: View changes
Status: Postponed » Active

Re-opening based on #2167021: Revamp Libraries API integration

The important use-case that was not mentioned is declaring Libraries API libraries as dependencies of non-Libraries API libraries. I.e. if my mymodule.admin system library wants to depend on Backbone.js, which is registered with Libraries API.

rjacobs’s picture

I'm trying to relate some of this back to the recent related D8 core discussion in #2350877: Deprecate/rename drupal_add_feed(), drupal_add_html_head(), drupal_add_html_head_link(), drupal_add_http_header(), and allow to be set declaratively in #attached....

Lastly, (I know I'm repeating myself ;) bear in mind that hook_library() is fundamentally different to Libraries API. The potential overlap with hook_library() only exists for 1:1 library-to-module relationships.

I was wondering if someone could point me toward more clarification on that (it sounds like there is a separate conversation on this idea that I could reference)? I think I understand that implementing hook_library() (D7) and $module.libraries.yml (D8) only really makes sense for 1:1 relationships between 1 module and a library, but given that the job of libraries API is to allow multiple modules to leverage a common library installation, could this be a unique situation? Wouldn't it still be safe for Libraries API to implement that hook on behalf of (multiple) other modules given that it's still only one common library definition that's used (i.e. still 1:1 between the library and the Libraries API module)?

I might very well be missing something fundamental about that, but I'd still like to understand it better.

rjacobs’s picture

It looks like the related ref from core (D8) is now #2358727: Figure out what if anything libraries API needs for #attached support. Of course the reason for renewed interest in this issue, in addition to the point from #3, is that the pattern $form['myelement']['#attached']['libraries_load'][] = array('mylib'); is no longer possible in D8. Maybe this now needs to be marked as an issue against 8.x-3.x-dev with the potential for a backport?

Following-up on my comment above, I see that a 1:1 link between module and core library definition would be needed as each module declares its own unique files, etc. However, it would seem that Libraries API could accommodate for this by creating a separate core library definition per module. So if moduleA and moduleB declare the boomsauce library via hook_libraries(), but moudleA defines a boomsauce file that moduleB does not, the resulting core library definitions produced on their behalf could differ. I suppose this could open the possibility for load conflicts though, and for dependency management you still need some "canonical" form of a core library declaration, which may not be straightforward.

I'm also under the impression that the performance concerns from #1 are not issues in D8? It looks like the core library registrations are only altered/calculated during cache clears (as opposed to at load time).

tstoeckler’s picture

Version: 7.x-2.x-dev » 8.x-3.x-dev
Category: Feature request » Task
Priority: Normal » Critical

Yes, there is indeed no way around this now. This is the only way that Libaries API will be able to function even remotely in D8.

Wim Leers’s picture

This is the only way that Libaries API will be able to function even remotely in D8.

Hm, sounds like you're not entirely convinced that it's a good thing? :(

AFAICT everything is stricter, better, more precise. The "load conflicts" problem is inherent to what Libraries API tries to do, and is most definitely also a problem in D7.

tstoeckler’s picture

In theory I'm quite convinced that it's better, no worries. :-)

I'm just not excited because it means a lot of work before Libraries API will work at all and I'm also a bit afraid that there are some use-cases that we haven't considered that we are making impossible in D8. Not that I know of any concretely, but I fear we will uncover them with Libraries API.

Edit: Stupid phone, Libraries, not Librabies

Wim Leers’s picture

Librabies

:P


I'm just not excited because it means a lot of work before Libraries API will work at all

Can you elaborate? AFAICT it is less work, because Libraries API now just invokes its hook (like in D7), then exposes that information using the standardized asset library system. There's no more need for exposing its own hooks. Which means there's less things that the D8 Libraries API module needs to do! Less to test, less to support, etc.

What am I missing?

vorapoap’s picture

Why module developer has to define hook_libraries_info at all?
Why don't we standardize this info into YML as other yml files?
Should Library API be implemented as Drupal8 Service?

Is it a long way after Drupal8 release before someone making this really usable and feasible?

We can make use of the similar Libraries API file structure to store third party module..
But that's all I think we can make use of.....just rewrite it as service, and replace the old fashion with YML (or even JSON)

Wim Leers’s picture

#10: 99% of the time, you'll be able to use a *.libraries.yml file. It's only for external libraries, that this module is necessary, and no YML file can be used. Because many modules depend on some non-opensource JS library that has many different versions, which means users have to manually download it and put it in a certain directory, which is where this module comes in with centralized/standardized logic for reliably detecting the presence and version of these external libraries, and then making them available to Drupal via hook_library_info_build(). Modules can provide the necessary parameters for *this* module by implementing something like hook_libraries_info().

It's trickier than it seems on the surface ;) Many projects outside Drupal simply don't deal with this, because they consider copy/paste programming "good enough".

vorapoap’s picture

@wimleers

I think I quite understand what Libraries API is for and the complexities beneath it. Our Drupal8 site have come across this for more than few times already. I clearly understand the need of central storage for 3rd party libraries. But until it can really work, my team now build an interim solution to store and load those JS files. And we all know it is not just JS. The library like PHPExcel and mPDF also need a central storage

Symfony has enabled us to use the vendor directory with composer. Could that be utilized for Libraries API?

And I think I heard the direction of Drupal that it is shifting away from hook mechanism? https://www.drupal.org/node/1509164

My proposal is that module developer define a special keyword in .libraries.yml that understood only by Libraries API but found to be normal library declaration by Drupal core.

And by that, maybe Libraries API may act as a facilator doing some versioning or dependencies control or even be a third party installer. That is what I am not sure at this stage.

What I am sure are
- I do need a systematic way of storing 3rd party lib centrally
- Those richful information defined in hook can be defined in YML.
- And global Libraries API functions can be better replaced with Drupal8 Service

------

rjacobs’s picture

Version: 8.x-3.x-dev » 7.x-2.x-dev
Priority: Critical » Normal

I'm scanning this issue in the interest of issue queue housekeeping.

From #6:

Yes, there is indeed no way around this now. This is the only way that Libaries API will be able to function even remotely in D8.

So we know that this is the future, at least for 8.x-3.x

From #12:

My proposal is that module developer define a special keyword in .libraries.yml that understood only by Libraries API but found to be normal library declaration by Drupal core.

This might be a bit analogous to what has started to shape via Tobias's work in #2090623: Turn hardcoded library_load_files() into a more modern, flexible system (though I'm not sure if I'm reading the comment correctly). The difference is that the "special keyword(s)" would be defined in the module's .info.yml file, but they would still be a mechanism to register a dependency with Libraries API (with the library metadata notably defined centrally somewhere else). See this comment for more.

Se also some of the (drafty) 8.x-3.x overview info in #1704734: [master] Libraries API 8.x-3.x.

So in many ways I believe this is now being addressed in #2090623: Turn hardcoded library_load_files() into a more modern, flexible system for 8.x-3.x, and could probably be framed in a proper context there for further discussion. Because of that I'm going to get bold and move this back to 7.x as I think that's where any pending discussion may apply (e.g. if there is interest to backport some of these ideas). However if anyone wants to override that and keep a 8.x discussion going here I won't be offended :)

tstoeckler’s picture

Actually I would be in favor of closing this. Once we have a stable D8 version I think we can backport that to D7 and get all the functionality there, too. I have no problem - generally - of independently developing the D7 version, but in this case we are hitting exactly those roadblocks which we are aiming to resolve in the D8 version from the get go.