Updated: Comment #179
Problem/Motivation
drupal_get_path() infiltrates almost every module and isn't very intuitive for new developers.
Stream wrappers make much more sense and simplify the API for developers trying to refer to image, JS, CSS and other assets files in code.
Stream wrappers will make it easier to reference JS and CSS files from yml files in modules, e.g. *.libraries.yml and will support the API to be introduced by #1762204: Introduce Assetic compatibility layer for core's internal handling of assetsAssigned to: sdboyer
Proposed resolution
Consensus is to go with the module:// theme:// and profile:// streamwrappers. Replace drupal_get_path() with stream wrappers in strings that are evaluated for a module, theme or profile path. Documentation will specify that this is *not* to be used to include PHP files.
Before patch examples:
_drupal_add_css(drupal_get_path('module', 'theme_test') . '/css/base-override.css');
$render_array['#attached']['css'][] = drupal_get_path('module', 'theme_test') . '/css/base-override.css';
After patch examples:
_drupal_add_css('module://theme_test/css/base-override.css');
$render_array['#attached']['css'][] = 'module://theme_test/css/base-override.css';
There are 4 possible use cases:
Asset files attached in PSR-4/PSR-0 classes:
In a \Drupal\foo_module\Form\FooEntityForm where assets are attached,
$form['#attached']['css'][] = 'module://foo_module/js/foo_bar.js';
is a far better DX than
$form['#attached']['css'][] = __DIR__ . '/../../js/foo_bar.js';
or even
$form['#attached']['css'][] = drupal_get_path('module', 'foo_module') . '/js/foo_bar.js';
Modules that provide resources consumed by other modules or themes
- color module
- ckeditor module
Modules that use resources provided by other modules
Mainly in contrib, these would utilize js, css and other files from modules in core.
Hooks for asset management
hook_library_info_alter(), hook_library_alter(), hook_css_alter(), etc. existing examples in system.api.php
The real benefit of this issue is the DX win of using "module://foo_module/js/foo_bar.js" which makes it easier to understand the code.
Remaining tasks
Reviews.
Commit.
Replacement of most / all uses of drupal_get_path calls (separate issue). This can be scripted.
API changes
Simplifies getting paths to modules, themes and profiles by using a stream wrapper.
#2028109: Convert hook_stream_wrappers() to tagged services.
#1308054: Add an abstract DrupalReadOnlyStreamWrapper that other stream wrappers can extend
#1762204: Introduce Assetic compatibility layer for core's internal handling of assetsAssigned to: sdboyer
#1702958: Add libraries:// stream wrappers to access system files
I wrote http://drupal.org/project/system_stream_wrapper and now let's merge it into core! It's super helpful to be able to access files via module://modulename/path/to/file.txt which nicely resolves to the actual file location.