Quantcast
Channel: Issues for Drupal core
Viewing all 293129 articles
Browse latest View live

[meta] D8 Extension System: Discovery/Listing/Info

$
0
0

Objective

  1. Work on some installer related issues revealed that HEAD contains plenty of insane call chains in code relating to discovering and listing extensions.
  2. Some of these call chains are causing an infinite recursion when calling the wrong function at the wrong point in time, because calls are hopping through legacy procedural global state and OO code and back.
  3. On top, ~40% of DrupalKernel consists of very complex code and undocumented logic that only exists in order to cope with the fragile legacy extension discovery/listing code.
  4. We need to fix this before release.

Goal

  • Replace the entire legacy code with dedicated Extension component classes.

Preface: Drupal's Extension Architecture (current)

  1. There are 4 extension types: profile, module, theme, theme_engine.
  2. Every extension type has a standard file extension; e.g.: bartik.info.yml
  3. Extensions are selectively discovered by extension type; e.g.: 'theme'
    1. Extensions of a certain type are expected to be located in a type-specific subdirectory; e.g.: ./themes
    2. Extensions are supplied by (1) Drupal core (2) An installation profile (3) The developer/site builder/end-user.
    3. To discover extensions, the installation profile and its directory must be known; e.g.: /core/profiles/standard
    4. Extensions are searched in multiple filepaths: (1) /core/$type (2) /$profile/$type (3) /$type (4) /sites/$site/$type
    5. If the same extension is found in multiple locations, then the later location overrides the former — unless the later one is not compatible (whereas "compatible" is limited to a Drupal core major version compatibility check as of now).
    6. The list of available/discoverable extensions is not expected to change within a single request at regular runtime.
    7. Extensions are normally not discovered while serving regular page requests.
  4. A list of enabled/installed extensions is stored in configuration instead.
    1. The current extension list and their filesystem locations are compiled into the service container.
    2. If the configured list of extensions is changed, the service container needs to be rebuilt.
  5. Each extension is required to provide an $extension.info.yml file, which contains meta information to describe the extension (package).
    1. The meta info of an extension/package is normally not used while serving regular page requests.
    2. Info Exception #1: Themes require their full meta information in order to operate. Therefore, the full theme meta info is persistently cached and retrieved from cache on every request.
    3. Info Exception #2: Various administrative user interfaces need to output the human-readable label of a module and thus need to retrieve meta info.
    4. Info Exception #3: Various subsystems/services need to know the installed version of an extension.
      (Applies to contributed extensions only. Core has a fixed version constant defined in code. Custom extensions do not have a version, unless a git commit hash can be determined from .git.)

Inventory/Stock-Check

DrupalKernel::getModuleFileNames()DrupalKernel::moduleData()

Manually (1) scans for all installation profiles to (2) retrieve the path of installed profile, so as to (3) discover all applicable modules.

The resulting module/filepath map is compiled into the %container.modules% parameter.
The %container.modules% data is used to register module namespaces.

Automatically invoked whenever the service container is rebuilt.
The service container is rebuilt either by Drupal via DrupalKernel::updateModules() or manually via rebuild.php.

drupal_get_filename()

Legacy. A static variable that maps an extension to a filesystem path.

Formerly primed by system_list() with module and theme data retrieved from persistent cache.
system_list() is only used for theme data today.
Neither DrupalKernel nor ModuleHandler are priming the paths for modules in HEAD, which causes any module/profile filename retrieval to be a cache miss.

On cache miss,

  1. for type module, the %container.modules% parameter is retrieved via ModuleHandler::getModuleList(), if that service available.
  2. a system.$type.files state record is looked up, if the state service is available, and even though that record is only written by system_rebuild_$type_data() (and not by SystemListingInfo).
  3. otherwise, a full filesystem scan is performed for the requested extension type via SystemListingInfo. The results are statically cached, so as to only scan once per request.
drupal_get_path()
Legacy. return dirname(drupal_get_filename($type, $name));
drupal_system_listing()
Deprecated. → SystemListingInfo
SystemListing
Obsolete. Scans for extensions of a given type using explicitly passed-in installation profile directories (without validating compatibility). Currently used by DrupalKernel.

Was seemingly invented to work around a circular dependency: SystemListingInfo needs to know the installation profile in order to discover extensions.

However, there is a logic error in SystemListingInfo in the first place; when asked to scan for profiles, SystemListingInfo triggers an infinite recursion to itself. The circular dependency and infinite recursion problem is solved with a trivial condition to skip the installation profile path retrieval in case available installation profiles are discovered.

SystemListingInfo

Scans for extensions of a given type using the current installation profile(s) and validates compatibility of extensions that intend to override previously discovered extensions.

Seemingly intended to serve as drop-in replacement for the legacy drupal_system_listing(), which was not only used for extension discovery by Drupal core, but also re-used by some contributed modules to scan for arbitrary extension-alike concepts. For example, the contributed Libraries API module discovers libraries in all /libraries directories, using the identical core/profile/site filesystem path resolution like the extension discovery in core.

The support for alternative use-cases makes this class and its usage unnecessarily complex and prevents us from optimizing it for its primary extension discovery use-case.

system_rebuild_module_data()
Legacy.
  1. Discovers all available modules (and installation profile(s))
  2. parses + enhances meta info
  3. allows already installed modules to alter meta info
  4. manipulates status + weight of enabled modules
  5. stores the result in a system.module.files state record.

The generated system.module.files state is consumed by drupal_get_filename().

system_rebuild_theme_data()
Legacy. Calls ThemeHandler::rebuildThemeData() to
  1. Discover all available themes and theme engines
  2. parse + enhance meta info
  3. allow modules to alter meta info
  4. apply basic parent/sub theme info inheritance logic.

Then proceeds and

  1. manipulates status + weight of enabled themes
  2. stores the theme data/info result in a system.theme.data state record
  3. stores the filesystem paths in a system.theme.files state record.

The generated system.theme.data state is consumed by system_list().
The generated system.theme.files state is consumed by drupal_get_filename().

Except for the parent/sub theme info inheritance logic, the basic meta info operations performed for each extension are identical to system_rebuild_module_data().

The parent/sub theme info inheritance logic is incomplete, both system_list() and later on ThemeHandler::listInfo() are performing additional inheritance logic.

install_profile_info()
Legacy. Parses meta info for a particular installation profile, applies defaults, and ensures required base system module dependencies.
system_get_info()
Legacy.
  1. For type module, force-invokes module discovery via system_rebuild_module_data() (once per request) and returns the meta info, if the module is enabled.
  2. For type theme, retrieves the cached data from system_list(), if the theme is enabled.
ProjectInfo
Utility class to perform some specific processing and validations for additional information that is automatically added to extension meta .info.yml files by drupal.org packaging scripts.
system_list()
Legacy. Cache item wrapper. Primes drupal_get_filename() with theme and theme_engine filepaths. On cache miss:
  1. Reads list of enabled themes from system.theme:enabled
  2. Consumes system.theme.data state record or calls system_rebuild_theme_data() to rebuild it.
  3. Calls ThemeHandler::getBaseThemes() to determine the base themes of each enabled theme based on meta info.
  4. Sets the theme engine for each theme.
list_themes()
Legacy. → ThemeHandler::listInfo()
ThemeHandler::listInfo()
Retrieves list of enabled themes and copies meta info properties into theme file object properties.

Calls system_list(), or manually system_rebuild_theme_data() upon failure/exception.

system_list_reset()
Legacy/obsolete.
  1. Resets static caches of system_list(), system_rebuild_module_data(), list_themes().
  2. Clears persistent cache of system_list() and system_get_module_info()/ModuleInfo.
  3. Deletes system.theme.data state record.

In short: All static and persistent extension meta info caches are cleared.

YamlDiscovery
Independent utility class to discover and parse YAML files in a given set of directories. Primarily used by Plugin Managers, like this:

<?php
$discovery
= new YamlDiscovery('routing', $this->moduleHandler->getModuleDirectories());
foreach (
$discovery->findAll() as $provider => $info) {
}
?>

Since the extension directories are injected as a dependency, this info file discovery + parsing tool cannot be used to discover the extensions themselves.

Data sources

$settings['install_profile']
The name of the installation profile Drupal was installed with.
(Only the name, not its filesystem location.)
simpletest.settings:parent_profile
Only exists when a (web) test is executed by Simpletest: The name of the installation profile of the parent site (test runner).
(Only the name, not its filesystem location.)

Enables tests using a particular installation profile to also find extensions in the installation profile of the parent site. Too complex to summarize in a few words; to learn more, see #911354: Tests in profiles/[name]/modules cannot be run and cannot use a different profile for running tests

Used by DrupalKernel::moduleData() and SystemListingInfo.

system.module:enabled
The configured list of enabled/installed modules, sorted by weight.
system.theme:enabled
The configured list of enabled/installed themes.
(Theme engines are not included.)

Application environment conditions

Exactly two:

Regular runtime
$settings['install_profile'] must exist, extension discovery and resulting listing depends on it.
(Early) Installer
There is no profile yet, extension discovery only lists (1) core extensions and (2) installation profiles.

Previously, there was a 3rd condition of update.php, which was not able to assume that the installation profile of a previous major version of Drupal core still exists, but that case is obsolete and gone with Migrate in core.

Proposed solution

Clean Inventory

  1. Extension\Discovery
  2. Extension\List
  3. Extension\Info
Drupal\Core\Extension\ExtensionDiscovery

Pretty much replaces SystemListingInfo as-is, but tailors its architecture, implementation, and API to its primary use-case.

Since the assumption that available/discoverable extensions are not supposed to change within a single request is sound/reasonable, this could be a static utility class or singleton.

Regardless of implementation, the results should be statically cached, so as to prevent multiple filesystem scans triggered by different services that would yield the exact same result within a single request.

The extension discovery process will return SplFileInfo objects instead of the custom anonymous objects that just happen to have $uri, $filename, and $name properties. If time permits, we will wrap (extend) SplFileInfo in an Extension class.

To profile/benchmark: A single + highly optimized filesystem scan for *.info.yml

  1. could be a lot faster than separate scans per type, especially given that we almost always scan for all extension types in case extension discovery is triggered anyway
  2. could leverage the new required type: [type] property in .info.yml files (even more so, if we'd require it to be defined on the first file line)
  3. would allow us to get rid of hook_system_theme_info(), which allows modules to ship with themes and only exists for simpletest.
Drupal\Core\Extension\ExtensionList / ExtensionHandler

Replaces legacy system_list(), drupal_get_path(), drupal_get_filename().

Central service to lookup filesystem location of a particular extension.

Uses core extension configuration to determine enabled extensions.
Uses the (1) service container [for modules/profiles] and/or (2) state records to retrieve filesystem paths.

-drupal_get_path('module', $name);
+$extensionList->getPath('module', $name);
+$extensionList->getModulePath($name);

Allows the /admin/modules page and rebuild.php to explicitly clear state information and rebuild it via ExtensionDiscovery, but otherwise, the existing state records are always used for lookups, and any kind of automatic rebuilding is strictly prohibited.

Partially represented in the form of ModuleHandler and ThemeHandler already, whereas the list facility of ModuleHandler is actually just the %container.modules% service container parameter at regular runtime.

ThemeHandler has no direct equivalent to ModuleHandler::getModuleList(); i.e., just the map of extension names to filesystem locations.

There is neither a ThemeEngineHandler nor a ProfileHandler yet. We either need to add those, or especially because the extension list logic is the same for all, that asks for a base ExtensionList/ExtensionHandler.

Also:

<?php
// Check all enabled + supported core extensions for whether they have Fu.
$skills = array();
foreach (
$extensionList->getTypes() as $type) {
 
$skills[$type] = $extensionList->discover($type, 'fu.info.yml'); // might be YamlDiscovery
}
return
$skills;
?>
Drupal\Core\Extension\ExtensionInfo

Replaces legacy system_rebuild_module_data(), system_rebuild_theme_data(), system_get_info(), install_profile_info(), system_get_module_info(), ModuleInfo, system_list(), list_themes(), ThemeHandler::listInfo(), etc.pp.

Central service to retrieve, process, and prepare meta info of all core extension types, and also store them in state (probably à la CacheCollector, but no, that is state information.).

State invalidation follows the ExtensionList/ExtensionHandler concept; i.e., only when explicitly requested. — That said, invalidation will probably have to be synchronized with ExtensionList/ExtensionHandler, so I'm not sure whether this facility should not be an integral part of ExtensionList/ExtensionHandler instead of a separate class/service.

Because our time to release is very limited, and because we have exactly 4 extension types in core, and because all of this is strictly bound and tailored towards the extension types we have in core, the concrete proposal is to simply hard-code the necessary post-processing for each extension type into this class/service — i.e., no subclasses or domain objects for each extension type.
(An extensible extension system is D9 material.)

Data sources

  1. -$settings['install_profile'] = 'standard';
    +$settings['install_profile']['standard'] = 'core/profiles/standard';

    The filesystem location of the installation profile is required in order to efficiently discover + rebuild extension lists.

    This setting is not supposed to be touched by site builders/developers either way, so the exact data type/value in settings.php should not matter.

    Additionally, this opens the door to add support for #1356276: Make install profiles inheritable, potentially even post-8.0.0.

  2. -$conf['simpletest.settings']['parent_profile'] = 'openatrium';
    +$settings['simpletest_parent_install_profile']['openatrium'] = 'profiles/openatrium';

    ...or completely obsolete with (1), because with that, reality is just this:

    $settings['install_profile']['openatrium'] = 'profiles/openatrium';
    $settings['install_profile']['standard'] = 'core/profiles/standard';
  3. -system.module:enabled
    -system.theme:enabled
    +core.extension:modules
    +core.extension:themes

    /core/config/core.extension.yml (← "core.extension" == Drupal\Core\Extension)

    Introducing core configuration. (restricted to critical base system components)

    Resolving a major circular dependency problem in the installer, tests, and elsewhere: System module cannot be installed through regular means, because System module itself supplies the system.module configuration file.

    Likewise, #2184387: Remove SchemaStorage discovered that System module defines some basic configuration schema data types that have to be available at all times. But yet, for concistency, DX, discovery, and code re-use purposes, it would be preferable to keep defining them in a YAML file like all other config schema files.

    /core/config/schema/core.data_types.yml

    The idea is to turn "core" into extension and extension type itself.

    So as to allow it to be a regular data provider like any other extension type. The only exception is that there is only one core, so $extensionList->getPath('core', 'whatever') will always return "core" (the extension name is ignored).

    Starting from core services (core.services.yml), to core libraries (core.libraries.yml), to base config schema, and base system extension (default) configuration, core already is a data provider like any other extension:

    /core/config/schema
    /core/config
    /core/lib
    /core/tests
    /core/core.libraries.yml
    /core/core.services.yml

Action plan

All of the legacy functions listed above are actively used all across core. A brutal/blatant rewrite and complete replacement attempt (1) would result in an unreviewable patch and (2) is unlikely to succeed due to sheer size and commit conflicts.

But we can split the effort into discrete phases:

  1. #2185559: Extension System, Part I: SystemListing clean-up + performance; remove SystemListingInfo + drupal_system_listing()
  2. #2188661: Extension System, Part II: ExtensionDiscovery
  3. Extension System, Part III: ExtensionList
  4. Extension System, Part IV: ExtensionInfo

Blockers

The primary purpose of this meta issue is to (1) raise awareness of the (non-obvious) problem space, (2) discuss the concrete proposal presented here, and (3) come to an agreement ASAP.

Given that other issues required me to make myself familiar with all of this code/insanity, I'd be happy to volunteer on my own to code up these gems, but before doing so, I'd like to achieve at least some basic level of agreement. (The devil is in the details anyway.)


tab_root_map and tab_parent_map notices undefined in _menu_translate()

$
0
0

things done:
1. put site in maintenance mode
2. copied all drupal files thru ftp (except the sites folder)
3. run update.php

after I went to front page, these error showed up

Notice: Undefined variable: tab_root_map in _menu_translate() (line 749 of .../includes/menu.inc).
Warning: implode(): Invalid arguments passed in _menu_translate() (line 749 of .../includes/menu.inc).
Notice: Undefined variable: tab_parent_map in _menu_translate() (line 750 of .../includes/menu.inc).
Warning: implode(): Invalid arguments passed in _menu_translate() (line 750 of .../includes/menu.inc).

did I do something wrong?

PostgreSQL orderBy method adds fields it doesn't need to, leading to fatal errors when the result is used as an insert subquery

Add an AnonymousUserSession object in favour of using drupal_anonymous_user()

$
0
0

Updated: Comment #N

Problem/Motivation

We are using drupal_anonymous_user() is quite a few places. Procedural and OO code. If we were creating a user session, we would use new UserSession(). Which drupal_anonymous_user is just a wrapper around. Also, the default values passed in are mostly not needed (exception hostname).

Proposed resolution

Introduce an AnonymousUserSession class, and use that instead of calling drupal_anonymous_user(). Set the hostname in the constructor, as well as not allowing any values to be passed in like UserSession. The anonymous user object should not change.

Remaining tasks

Patch, reviews, agreement

User interface changes

None

API changes

Removal of drupal_anonymous_user(). Although if we *have to*, we could keep the drupal_anonymous_user() to preserve any BC.

Change record: Phase 2 - Decouple book module schema from menu links

$
0
0

Problem/Motivation

The re-use of the {menu_links} table by book module has always been a bit of an awkward implementation. I (pwolanin) wanted to build book on tops of the menu link hierarchy handling and by the end of the 6.x cycle, there wasn't time left to do it better than this.

However, looking at the code in book module, a lot will need to be re-factored in terms of queries to decouple from the old router system, so we might want to clean it up.

Also, there is no good reason to have book links be actual menu link entities. In fact, the coupling now between the book module and menu link code is blocking needed finalization of menu link entity since like removing ArrayAccess

Proposed resolution

Combine all the book link fields into one table - essentially copying the hierarchy-related elements from {menu_links}

Simplify the access checking code since we know that all the links will be to nodes.

API changes

The schema will change, and we will move all the APi functions to the book manager behind an interface so that further refactoring can be accomplished, or the implementation changed.

#2100575: [META] - Split book module from menu link

[policy, no patch] Trait strategy

$
0
0

Problem/Motivation

In light of #1498574: [policy, no patch] Require PHP 5.4 being approved by Dries, we will have Traits available to us for Drupal 8. Yay! OK, so where do we want to use them?

Remember, traits are *not* an alternative for proper object composition. Their main use is for reducing boilerplate code and providing utility code without relying on inheritance. Crell would describe them as "a cleaner alternative to utility base classes".

It general, traits, like interfaces, should be small and focused. It is *really really easy* to include multiple traits in a single class, and ends up being nicely self-documenting.

Note that traits may not implement an interface; however, a class may implement an interface by using a trait that happens to do so. For example: http://3v4l.org/07EQM

Proposed resolution

Draft policy:

General guidelines

  • All abstract base classes SHOULD be considered as possible candidates to replace with one or more traits, particularly if they are used primarily for code sharing and not "is a special case of" relationships. (Reason: abstract classes often exist only to provide incomplete partial implementations, which traits do as well but without "stealing" the "is a special case of" relationship.)
  • Traits SHOULD be single-purpose. That is, ControllerBase should not be unilaterally replaced with ControllerTrait, but the various bits and pieces of ControllerBase MAY be replaced with multiple targeted traits.
  • Traits used for common application-level dependency injection (like translation) MUST include an override method for easier testing.
  • Traits used for common application-level dependency injection (like translation) SHOULD use private variables. (This helps enforce the previous point.)
  • An Interface that implies two or more "this method will be identical for 99% of all implementers" methods SHOULD provide a trait that does so, and SHOULD NOT provide an abstract base class.
  • Infrastructure-level and domain-level classes (ie, things that we do want to unit test in the majority case) MUST NOT use traits as an alternative to proper dependency injection. ONLY application-level code (controllers, forms, etc.) should do that. (They may still use other traits as appropriate, but not as an alternative to dependency injection.)
  • Services surfaced in \Drupal are good candidates to consider offering a trait for, but that does not imply that there should be a 1:1 correlation between the two.

Possible candidates for conversion

ControllerBase
Probably can get split up to lots of small traits; MAY be removed entirely
FormBase
The same utilities that are on ControllerBase can be removed in favor of traits. Default form implementations MAY be replaced with a trait, TBD.
PluginBase
The same utilities that are on ControllerBase can be removed in favor of traits. We should investigate if other aspects can be replaced with traits, too. TBD.

Proposed application-level traits

Translation
$this->t(). See #2079797: Provide a trait for $this->t() and $this->formatPlural().
EntityManager
$this->entityManager()
Configuration
$this->config() (returns a config object, not the factory)
DependencySerialization
The bridge code to make an otherwise unserializable object serializable through the DIC. See #2208115: Add DependencySerializationTrait.
ActiveUser
$this->currentUser() (should this be called account, since that's the actual object that's returned?)
UrlGenerator
$this->generator() (should this return the generator service, or be multiple methods for the various generator methods?)

Remaining tasks

  1. Agree on standards/policies/guidelines for using Traits.
  2. Make a Coding Standards page under https://drupal.org/coding-standards describing these guidelines, or add it to the existing page on classes/interfaces (https://drupal.org/node/608152)
  3. Agree on which classes to convert to using Traits.
  4. File separate issues to convert those classes to using Traits.
  5. Make sure that api.drupal.org can deal with Traits -- which will involve updates to the Grammar Parser and API module projects.

User interface changes

None.

API changes

Some abstract and/or base classes will be converted to using the PHP 5.4 "Traits".

Regression: routing / tabs / actions / contextual links lack way to attach replacement arguments to UI strings

$
0
0

Problem/Motivation

In #2114069: Routing / tabs / actions lack way to attach context to UI strings we are adding context to UI strings to handle the case of ambiguous items like "Extend" and "Views". However tabs / routes / actions may also equally need title replacement values. The menu system supported these so this is a regression that we only allow static strings. This results in problems that derivative tab titles, eg. 'Translate @type' don't work, where we'd derive @type from elsewhere. See #2119497-9: Default local tasks are not to be assumed $route_name . '_tab' point 1.

Proposed resolution

Add support for replacement arguments that routes/tabs/actions would be able to provide. This will round out the arguments of t() to be supported.

Remaining tasks

- Do it.
- Write tests.
- Review.
- Commit.

User interface changes

None.

API changes

TBD

#2114069: Routing / tabs / actions lack way to attach context to UI strings

Make ConfigEntityType::getKey() enforce the UUID key

$
0
0

Updated: Comment #0

This is a follow-up to #2198377: Enforce UUID key name in configuration entities

Problem/Motivation

The committed patch in #2198377: Enforce UUID key name in configuration entities forces consuming code to check whether a given entity type is config or content entity type in order to figure out the UUID key. Post-commit it was discussed there whether it would not be possible to make EntityTypeInterface::getKey('uuid') return 'uuid' in all cases for config entities directly. This would improve DX.

Proposed resolution

Make ConfigEntityType::getKey('uuid') return 'uuid' in all cases.

Remaining tasks

User interface changes

-

API changes


Enforce UUID key name in configuration entities

$
0
0

Problem/Motivation

We pretend that we can configure the UUID key in configuration entity annotations yet we hard code it.

class ConfigStorageController extends EntityStorageControllerBase implements ConfigStorageControllerInterface {
  /**
   * Name of the entity's UUID property.
   *
   * @var string
   */
  protected $uuidKey = 'uuid';

vs
* @EntityType(
*   id = "view",
*   label = @Translation("View"),
*   controllers = {
*     "storage" = "Drupal\Core\Config\Entity\ConfigStorageController",
*     "access" = "Drupal\views\ViewAccessController"
*   },
*   admin_permission = "administer views",
*   config_prefix = "views.view",
*   entity_keys = {
*     "id" = "id",
*     "label" = "label",
*     "uuid" = "uuid",
*     "status" = "status"
*   }
* )

In #2080823: Create API to discover content or config entities soft dependencies and use this to present a confirm form on module uninstall we need to be able to work with configuration entities without the entity type actually existing. The only requirement this introduces is that the uuid key is always uuid - which it is. We just make it look like it is not. So this actually does not block that patch.

Proposed resolution

Remove uuid from all config entity annotations.

Remaining tasks

Build consensus
Review patch

User interface changes

None

API changes

None

proof pictures for a picture sitemap

$
0
0

Hi, with drupal 8 we have now in core the ability to upload responsive images in a field and via the core wysiwyg module. Wim Leers fixed here https://drupal.org/node/2061377 a big Problem from a View by an End-User.
And we have to make sure thats Drupal is going more for a End User. I know someone think here Drupal isn´t for a End-User but this View is WRONG We need to make sure thats Drupal covers all the thing thats needed Today - without Trouble and in a View of a upcoming Upgrade. So this REQUEST is to make sure thats all the Pictures we can Upload in the new D8 Version needs to proof thats the Pictures have the Option to add by a Picture Sitemap or third party module like https://drupal.org/project/media_sitemap.
sorry for my english
cheers

Dropbutton style update

$
0
0

Problem/Motivation

Tables have seen little issues, the only improvement we saw was to remove some of the distracting elements and improving the whitespace.

We developed Proposal: A Style Guide for Seven. This issue aims to introduce the proposed styling for tables to core.

To quote the rationale provided:

To improve the ratio of information to UI chrome, this guide recommends removing zebra striping and using thin rules to separate table rows. A progressive enhancement creates a subtle highlight on the hovered table row, allowing the eye to more easily move horizontally along the row, even when large stretches of whitespace appear between cells contents. (Note that this effect, being an enhancement, has no planned touchscreen equivalent and does not pass WCAG contrast standards.) For similar reasons, this style also removes left and right borders from the table and table cells.

The style used here for the sort-active table header cell is a motif carried through to other elements, such as secondary tabs and pagination. This consistency is both good for usability and for Drupal’s credibility (part of the brand).

Proposed resolution


Remaining tasks

  • Make a patch
  • Review accessibility
  • Implement this for the create content dropbutton

User interface changes

The dropbutton style will be changed, no functional differences.

API changes

None

Convert menu link SQL queries to the Entity Query API

Remove SchemaCache and CacheArray

$
0
0

Updated: Comment #N

Problem/Motivation

CacheArray has been deprecated. The only left-over use is SchemaCache, which was added in 7.x because the list of tables could get very long, especially due to configurable fields.

Proposed resolution

As field storage tables are no longer exposed in hook_schema() and a lot of tables have been dropped due to conversion to config entities, caches tables are created on-demand as well and are no longer in there. The expected amount of tables defined in hook_schema() will be much much smaller in 8.x. Maybe even the content entity storage tables will be removed. So the schema cache is small enough so that we won't have to worry about it anymore.

Therefore, drop SchemaCache without replacement, together with CacheArray.

Remaining tasks

User interface changes

API changes

CacheArray is removed, has been deprecated for a long time already.

Original report by @cosmicdreams

As a follow up to #1858616: Extract generic CacheCollector implementation and interface from CacheArray we should remove the deprecated CacheArray class and convert the final pieces of Drupal to use CacheCollector instead of CacheArray. Only two uses remain and two places within code comments.

Then we can put the parent issue to bed by writing a change notice.

Update textfield & textarea style

$
0
0

More Seven Theme issues:#1986434: [meta] New visual style for Seven

Problem/Motivation

A big part of this style guide is to find a consistent styling for our most basic elements. To do this we wish to change the text input slightly, mostly introducing a border radius and slightly changed background color. In Seven's initial design the hard corners where throughout core, however for the updated style we changed this to achieve a more softer look.

Right now its not clear to the amount of items we can stretch this but ideally this is something we can apply to all form elements unless specified differently.

We developed Proposal: A Style Guide for Seven. This issue aims to introduce the proposed styling for text input in core

To quote the rationale provided:

Text inputs are styled to be recognizable but not garish, with a subtle background tint (#f0f0f0). A slight softening of text inputs is achieved with a 2px border-radius; this is a subtle refinement that we use throughout form elements to subtly soften otherwise harsh corners. For consistency, we propose changing the D7 “throbber” to a “spinner” styled similarly to the progress bar component (see below) for consistency. To reduce UI clutter, the spinner would appear only while awaiting a response from the server.

Note that the required field marker is no longer red, both to reduce UI clutter (without removing information) and to allow red to be reserved exclusively for error states and danger actions.

Proposed resolution

Text fields redesigned

We propose to add a border radius of 2px, change the background color to #f0f0f0 , and remove the red required indicator.

Remaining tasks

  • Make a patch
  • Review accessibility

User interface changes

All input form element styles will be changed, no functional differences.

Test Pages

  • /core/install.php
  • /node/add/article
  • /admin/structure/views/view/content - Try changing a few settings
  • /admin/structure/views/add
  • /admin/structure/block - Try adding a block
  • /admin/structure/types/manage/article/fields/node.article.body

Convert theme_fieldset() to Twig

$
0
0

Issue #2152209 by steveoliver, joelpittet, hussainweb, shanethehat, jenlampton, kpa, AnythonyR, EVIIILJ, kgoel, Cottser, dsdeiz, hanpersand: Convert theme_fieldset() to Twig

Task

Convert theme_fieldset() to a Twig template.

Remaining tasks

  • Patch
  • Patch review
  • Manual testing
  • Profiling

Steps to test

@todo


Indexing status can show a negative percentage of content as having been indexed

$
0
0

Problem/Motivation

The Search settings page shows indexing status. There are inconsistencies in how it is calculated, which can lead to sometimes seeing negative percentages.

Proposed resolution

Make the calculation of settings consistent, and make sure the throttling settings are consistent with the numbers being displayed. Currently some calculations are using nodes and some are using translations of nodes. They should all use nodes.

Remaining tasks

Make a patch that makes sure throttling and counts are per-node and not per-translation. Also add tests to verify that throttling is being done that way. (See SearchMultilingualEntityTest, which is currently the only test for throttling and index status -- it would also be good if that test was updated to use the UI to set the value so that we would have more complete testing.)

User interface changes

Throttling and indexing status will consistently count nodes and not individual translations of them.

API changes

None.

Original report by @ianthomas_uk

I have a fully indexed site consisting of 6 nodes with some translations.

The indexing status box at admin/config/search/settings says "100% of the site has been indexed. There are 0 items left to index."

If I click the 'Re-index site' button, the message changes to "-100% of the site has been indexed. There are 6 items left to index."

That should read 0%.

Convert element_info() to a service

$
0
0

Updated: Comment #N

Problem/Motivation

@TODO

Proposed resolution

@TODO

Remaining tasks

@TODO

User interface changes

@TODO

API changes

@TODO

Make batch_set() more flexible to accept initial data available during the batch process

$
0
0

At the moment, batch_set() ignores any kind of initial data will be available in $context['results'] during the batch process, however this would be very useful in some cases.

Lets say I have a pretty large XML document which describes some kind of book. So I would like to import the data from this XML document using batch API, and at the end of the import process I would like to set a message with some basic information about the freshly imported book, including for example it's title and it's author. In other words, the title and the author attributes need to be available at the end of the batch process. More specifically, they need to be available in $context['results'], because this array will be passed to the batch finish callback.

To achieve the behavior described above, it would be very nice if I would place the book's title and it's author in the batch definition array somewhere next to other batch attributes before the the batch process starts, so they will be available in all batch operations (including the first one) and also in the "finished" callback. The simplest solution is to modify batch_set() to accept initial "results" attribute from the batch definition like this:

<?php
  $batch
= array(
   
'title'=> t('Importing book'),
   
'operations'=> $operations, // $operations defined earlier
   
'init_message'=> t('Initializing: book import'),
   
'error_message'=> t('An error occurred during book import.'),
   
'finished'=> 'book_import_finished_callback',
   
'results'=> array(
     
'book'=> (object) array(
       
'title'=> $book_title, // $book_title defined earlier
       
'author'=> $book_author, // $book_author defined earlier
     
),
    ),
  );
 
batch_set($batch);
?>

One advantage of the above solution is that it is require only 2 line changes in batch API. Another solution would be a new optional 'init_parameters' attribute (or something like this) in the batch definition, whose value would be copied into $context['results'] before the start of the batch process, or would be available next to it for example in $context['init_params'] or similar ways.

At the moment without these features one workaround can be if I pass book's title and book's author to each batch operation individually as a parameter, but this is a very ugly solution, because batch operation parameters should contain information only for the actual operation and not "shared" information available or used in all operations. Another workaround if I alter my own batch with hook_batch_alter() and inside of it I can pass "initial data" into $context['results'], because in here it is already available, and it won't be altered anymore before the start of the batch process. I guess, I don't have to say that this latter workaround even worse than the first one.

If any changes will be made, don't forget to update batch API's documentation according to the new feature(s).

Enable static caching for config entities

Explore addressable block rendering

$
0
0

after the WSCCI-ish call yesterday, i offered to pull out some of the relevant segments of code from princess that deal with addressable rendering. these are those pieces. hang on, this could be a bit of a rough ride, because there are key differences in how these systems are used by princess vs. core.

let's start with flow. in princess, the subrequesting process is managed by the DisplayController. it pulls up the current display's list of blocks to be rendered, gets each block ready to go (instantiate the block plugin, inject the block config, inject any contexts that are needed by the block), then passes that fully-loaded block object to another object, one that implements FragmentRendererInterface. in the patch, this is InlineBlockFragmentRenderer, specifically the render() method.

this fragment renderer is responsible for getting the content back - in princess, we represent this response as an HtmlFragment. currently, this logic forks in two - either it issues a subrequest by asking the BlockAddressGenerator for the appropriate addressed path, or it renders directly right on the spot, depending on whether or not the block has indicated that it is "addressable-safe". either way, though, it ends up being the responsibility of the DefaultBlockController to create the HtmlFragment. so, that's five-ish different systems with different scopes of responsibility, working in relative harmony to produce a subrequest response.

so in asciiart, it's something like this:

DisplayController --> FragmentRenderer --> HttpKernel --> DefaultBlockController
                                                                                \
                                                                                 \
                                                                             HtmlFragment
                                                                                 /
                                                                                /
                      DisplayController <-- FragmentRenderer <-- HttpKernel <---

most of the same rules apply to how we'd need to do this in core. we'd need:

  • some addressing routes routes. the 'standalone' one in the block.routing.yml i included should be sufficient.
  • some new config options on blocks that determine the rendering strategy to use. these may or may not have to be pushed to the interface.
  • a block controller...maybe. this is interesting, i'll come back to this.
  • a way to get MORE back than just a rendered string from the subrequest. there are options for this, as well, but it's tricky.

the function we'd target (or at least begin by targeting) is _block_get_renderable_region(). roughly speaking, i'd say that this logic would need to fork somewhat similarly to how the InlineBlockFragmentRenderer::render() logic does - either it uses a subrequest, or it doesn't. if it does, then it needs to initiate the subrequest, which it should probably do by asking the FragmentHandler (this does have issues; i'll get to that) to render. it'll need to pass along the config value that indicates the particular rendering strategy to use. it'll also need to make a choice about the controller to use. Symfony handles this with a ControllerReference concept...which maybe will work for us, maybe not.

here's where it gets a little tricky, though. entity_view() is the "controller" we rely on in the current code - that ultimately arrives at BlockRenderController. we need to make something else, though, because BlockRenderController isn't gonna cut it here as-is. the issue is a fundamental disconnect between what Symfony expects to come back out of a subrequest (a Response - and when it passes through Symfony's native FragmentHandler, that is further reduced to only the string body of the response) versus what we need (the response body, but also out-of-band information like assets and titles). this is the reason i came up with HtmlFragment in the first place - it gave us a place to piggyback data.

msonnabaum has often pointed out that HtmlFragment is not significantly different from a render array. this is true. but there are two differences that matter:

  • Symfony requires a Response be passed back from the controller targeted by the subrequest.
  • Currently, this render array is created via a monolithic method, BlockPluginInterface::build(). Which means we're currently all-or-nothing in our ability to get back a block's output, out-of-band or otherwise. note - the 'exception' is the clusterfuck we've made out of block titles where they're *sort of* gotten out of the configuration entity, which effectively makes them out of band (i'm trying to fix this in #2025649: Add title-related methods to BlockPluginInterface to help clarify and resolve many issues). princess has introduced methods on BlockPluginInterface at least in part to deal with these issues.

the DefaultBlockController in this patch won't help a lot, as it's designed around many of these additional methods.

what we need to do for core, i think, is cheat. that is, we need a block controller for core that takes the render array output of entity_view(), strips out-of-band info out of it, calls drupal_render(), stores the resulting string on a Response or subclass, send the response back up to the main request. THEN, upon receiving that response string back up in _block_get_renderable_regions(), we call entity_view()again, then go through and strip out the content-related stuff from the render array, leaving only the out-of-band information.

is this terrible? ohhh, yes. i'm pretty sure dante designated a special circle of hell for people who do things like this. but it fits the constraints. i think.

Viewing all 293129 articles
Browse latest View live


<script src="https://jsc.adskeeper.com/r/s/rssing.com.1596347.js" async> </script>