- ๐ฎ๐ณIndia Himani Khurana
Himani Khurana โ made their first commit to this issueโs fork.
Let's call it an anti-pattern in a component world to write a hook_preprocess_page and a hook_preprocess_node just all in the same file, while they are already scoped by their very nature to components (page & node in this example).
Currently Drupal core supports one .theme file per theme, and it's a convention is that we name it [themename].theme. However, most of the functions we write in there, are component-specific. So it doesn't make much sense to write component-specific functions in a theme-specific file. Writing all of these functions in a theme-specific file accommodates the frontend developer to work in a blob-way, where the concept of components is hard to follow.
Conceptually: The proposal here is to allow multiple [component-name].theme files. These PHP files would be able to do all the same things as the currently allowed .theme file, but now, we would have the option to create these files to be component-specific instead of theme-specific. It should be possible to have these files inside components inside a theme.
Technically: www.compony.io provides a theme that does this out of the box. The solution uses a `hook_theme` and inside there we do a file-discovery to find all the component-specific .theme files that exist inside the theme. Once we found them, we want to make them as fast as if you would only use 1 .theme file. We do this by storing all the locations to each component-specific .theme file in a theme-partials.php file. (Following the internal concept of Composer, which hardcodes the location of files in other php files on `composer install`.) A longer reasoning is available of this approach as a reference. The theme-partials.php file will only be created on cache rebuild, so this won't impact performance. A hook_theme will only be called after a cache clear, so it won't impact performance too.
The following example, has the assumption that all of the theme components are placed inside theme-name/components folder.
Let's assume this theme is called "compony" and in order to follow below example, let's assume we have a component called text-dropdown that exists under themes/custom/compony/components/.
The contents of this component can be inspected here as a demo: https://gitlab.com/componies/flat-design/Custom/text-dropdown
/**
* Implements hook_theme().
*/
function compony_theme($existing, $type, $theme, $path) {
// Get the name of the theme where this function is being called
$theme_name = basename(__FILE__, '.theme'); // compony
// Get the path of the theme where this function is being called
$theme_path = drupal_get_path('theme', $theme_name); // themes/custom/compony
// Create a variable that we will later turn in to an actual file, and open it up with the PHP opening tag.
$partials_content = "<?php \n";
// Iterate over all the files found in /themes/custom/compony/components/
$components = new RecursiveDirectoryIterator($theme_path . '/components/');
foreach (new RecursiveIteratorIterator($components) as $file) {
// Filter out all the files that have the extension: "theme"
if ($file->getExtension() == 'theme') {
// Let's assume we found a .theme file on /themes/custom/compony/components/text-dropdown/text-dropdown.theme
$pathName = $file->getPathName();
// Then we add to the $partials_content a check
// if the (path-to-component/text-dropdown.theme) exists, require it.
$partials_content .= 'if(file_exists("' . $pathName . '")) {' . "\n";
$partials_content .= 'require_once("' . $pathName . '");' . "\n";
$partials_content .= '}' . "\n";
}
}
// Once we've looped over all the .theme files,
// we will group all the paths found in this theme to a theme-partials.php file
// and put that inside the theme, as this is theme-specific.
$create_private_partials_file = file_unmanaged_save_data($partials_content, $theme_path . '/theme-partials.php', true);
return $themehooks;
}
So that was the creation of the theme-partials.php file. Next, we need to load it in on every page-load.
// Outside of any hook, straight in the compony.theme we require the theme-partials file:
$theme_name = basename(__FILE__, '.theme');
$theme_path = drupal_get_path('theme', $theme_name);
$partials_filename = $theme_path . '/theme-partials.php';
if(file_exists($partials_filename)) {
require_once($partials_filename);
} else {
// The very first pageload after a deploy, will create the partials file,
// but this if statement is ran just before it's creation,
// so we need to have a fallback for the very first page-load after a cache clear
// Otherwise you will only load in all the partial .theme files on second pageload
// after a cache clear.
$components = new RecursiveDirectoryIterator($theme_path . '/components/');
foreach (new RecursiveIteratorIterator($components) as $file) {
if ($file->getExtension() == 'theme') {
$pathName = $file->getPathName();
require_once($pathName);
}
}
}
Find someone that knows where this would fit in to core and write a patch.
Not applicable
Change documentation that a component can now have multiple .theme files.
Not applicable.
Active
11.0 ๐ฅ
Last updated
Not all content is available!
It's likely this issue predates Contrib.social: some issue and comment data are missing.
Himani Khurana โ made their first commit to this issueโs fork.