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

Move contact module footer link to standard install profile

$
0
0

Problem/Motivation

Contact module adds a link to the site-wide contact form in the footer menu
It has no right to do so, and means you cannot disable it later without killing the footer menu.
It belongs in the standard profile (product feature, not framework feature).

Proposed resolution

Move it

Remaining tasks

User interface changes

API changes

Data model changes


Add view builder for contact module's ContactForm entity

$
0
0

Problem/Motivation

When referenced in an entity reference field, the ContactForm entity has no 'rendered entity' output.

Proposed resolution

Add the view builder from Contact storage module to core.
Set this in the annotation for the ContactForm entity.
Add test coverage to verify that forms can be referenced from entity reference fields and doing so renders the message form.

Remaining tasks

All of the above

User interface changes

None

API changes

None

Data model changes

None

Send emails before saving the message

$
0
0

The MessageForm class on save() first sends the MailMessages and then it saves the message entity.

I need to send in the emails a URL to see the message entity, but I cannot do it because the message is not persisted yet (it doesn't have an ID).

Add test coverage for enabling/disabling base fields on MessageForm

$
0
0

Problem/Motivation

ContactForm adds a number of fields which are nicely exposed as extra fields. The problem is that a form must explicitly check if a component is enabled before adding it.

Proposed resolution

Wrap name, email and the other defined extra fields in
if ($component = $this->getFormDisplay()->getComponent('name')) {

Remaining tasks

User interface changes

API changes

Data model changes

Non-legacy alternative to hook_node_grants() and hook_node_access() functions

$
0
0

I have discovered the hook_node_grants() and hook_node_access() functions. This points to the legacy stuff in Drupal 8. Hooks should be avoided - events should be used instead. Is there any non-legacy solution in Drupal 8, which is replacing hook_node_grants() and hook_node_access()? Any events e.g.?

Fix hook_page_top implementation for node.module

$
0
0

The hook_page_top() implementation for the node module has a wrong definition. The function argument should be called $variables, not $page. And the node_preview form container should be added directly into the argument, not into a 'page_top' sub-key.

Hiding required fields that do not have default values results in an EntityStorageException (column cannot be null) when you try to save

$
0
0

Problem/Motivation

It is possible to hide the node title from the form display, but this causes an uncaught exception when saving the node because a title actually is required:

Uncaught PHP Exception Drupal\\Core\\Entity\\EntityStorageException: "SQLSTATE[23000]: Integrity constraint violation: 1048 Column 'title' cannot be null

Proposed resolution

Remaining tasks

User interface changes

API changes

Data model changes

Original Report

When adding new content for any content type for which the Title is hidden, it displays Error(as displayed below in the reproduce section).
It should instead add the content since the Title field is made as hidden and it is not visible for User to Add any more.

Steps to reproduce:
- Go to Structure -> Content types -> Basic page -> Manage form display -> Choose 'Widget' select box for Title to "-Hidden-". Then Save the form.
- Now try to add new content for Basic page.
- It displays "The website encountered an unexpected error. Please try again later."

System information:
OS: Windows 10
Web server: Apache/2.4.17 (Win32) OpenSSL/1.0.2d PHP/5.6.15

Node field with "Allowed Number of values = Unlimited" missing remove button


Profile page's title/heading does not fulfill hook_user_format_name_alter

$
0
0

I am not sure if this is an actual bug or not, so I assigned category "Support Request"

I've implemented hook_user_format_name_alter in a custom module, and it works perfectly. The newly formatted username that I have defined is being used instead of the default username value everywhere in the application. Everywhere, that is, except the heading on the user profile pages.

EXAMPLE:
Default Username: "123456"
Custom Username Defined by Hook: "customuser"

"customuser" is displaying for my user in the following places:

  • all views that include my user record (example, /admin/people and /admin/content),
  • the administrative toolbar
  • the raw url for my user profile, which shows "/user/customuser" instead of "/user/123456"
  • the heading on my profile's contact tab, which shows "Contact customuser" instead of "Contact 123456"

So, I'm wondering why the title on the main profile page is not affected by hook__user_format_name_alter, especially when the title on the contact page does fulfill the hook's definition. I tried setting up the following RouteSubscriber to override the title on the profile page, but doing so broke something and gave me an "Access Denied" message when trying to access my own profile page (even when testing this out on the admin account):

/**
 * @file
 * Contains \Drupal\MYMODULE\Routing\RouteSubscriber.
 */

// see: https://www.drupal.org/node/2187643

namespace Drupal\MYMODULE\Routing;

use Drupal\Core\Routing\RouteSubscriberBase;
use Symfony\Component\Routing\RouteCollection;

/**
 * Listens to the dynamic route events.
 */
class RouteSubscriber extends RouteSubscriberBase {

  /**
   * {@inheritdoc}
   */
  public function alterRoutes(RouteCollection $collection) {
    //Right now, this breaks the user's home page.
    if ($route = $collection->get('entity.user.canonical')) {
      $route->setDefaults(['_title', 'CUSTOM PROFILE TITLE']);
    }
  }

}

Thanks in advance for any assistance.

Node type body class is not present on node preview page

$
0
0

Problem/Motivation

On node pages there is a node type class of the form page-node-type-[node-type] however this class is not present on node preview pages, leading to preview pages not having the same styles as normal node view pages.

Proposed resolution

Add the node type class to the node preview pages also.

Move node constants to NodeInterface

$
0
0

Problem/Motivation

We should move constants(NODE_PUBLISHED, NODE_PROMOTED etc.) from node.module to a proper place. The node interface is a good one. The actual name can still be discussed.

Proposed resolution

  • NODE_NOT_PUBLISHED => NodeInterface::STATUS_NOT_PUBLISHED
  • NODE_PUBLISHED => NodeInterface::STATUS_PUBLISHED
  • NODE_NOT_PROMOTED => NodeInterface::OPTION_NOT_PROMOTED
  • NODE_PROMOTED => NodeInterface::OPTION_PROMOTED
  • NODE_NOT_STICKY => NodeInterface::OPTION_NOT_STICKY
  • NODE_STICKY => NodeInterface::OPTION_STICKY
  • NODE_ACCESS_ALLOW => NodeInterface::ACCESS_ALLOW
  • NODE_ACCESS_DENY => NodeInterface::ACCESS_DENY
  • NODE_ACCESS_IGNORE => NodeInterface::ACCESS_IGNORE

Remaining tasks

Needs code review.

User interface changes

None.

API changes

None.

Node preview shows and defaults to "Default" instead of "Full" view mode

$
0
0

Problem/Motivation

Default vs. Full is weird, there are a number of issues around that and the main problem is that getViewModeOptionsByBundle() and related methods return wrong data.

The default view mode is "full", which if not explicitly enabled will then fall back to the configuration provided by "Default". But the $view_mode argument *is* full.

One example where this breaks is if you have a node--$type--full.html.twig template, but the preview doesn't use that.

Proposed resolution

Changing those methods is hard, especially in 8.x. The patch that I will attach proposes a very simply workaround, we simply add Full sa the first option in the list, always.

Remaining tasks

User interface changes

API changes

Data model changes

Destination URL breaks preview

$
0
0

From #1510544: Allow to preview content in an actual live environment

I did accidentally find one other bug in testing: if you're at admin/content, and select "Edit" next to a node in the list, then click "Preview," instead of being shown the preview, you will be taken back to admin/content and your changes lost. I suspect that's because the URL you end up on is http://8.x.local/node/1/edit?destination=admin/content and this somehow screws with the preview system's use of URLs? Hm.

Oh yes, the destination parameter, we somehow lost that in the patch somewhere, I remember we used to store that property as well.
It's not /that/ hard to implement, but I'm AFK until monday. If we can wait that's fine, unless someone else takes that up. Also more than happy to fix that in a follow up. You can even assign it on me immediately :)

This has this bewildering effect:

  • On admin/content, edit a node.
  • Change stuff, click Preview.
  • You are returned to admin/content. Edit the node again.
  • The changes appear to have been saved by preview, but totally were not.

Logger throwing InvalidArgumentException when MigrateMessage receives TranslatableMarkup instance

$
0
0

InvalidArgumentException: $string ("Migration @id is busy with another operation: @status") must be a string. in Drupal\Core\StringTranslation\TranslatableMarkup->__construct()

This is happening when display($message, $type = 'status') in MigrateMessage.php (core/modules/migrate/src/MigrateMessage.php) receives a non-rendered TranslatableMarkup instance (rather than a string) as the $message from import() in MigrateExecutable.php (core/modules/migrate/src/MigrateExecutable.php, line 168). There are many instances in MigrateExecutable that call display() with a non-rendered TranslatableMarkup instance, resulting in the error above being thrown by the \Drupal::logger(), which expects a string (MigrateExecutable.php lines 127, 168, 184, 207, 284, 303, 475, 491, and 505). In some cases (such as line 284 of MigrateExecutable.php) the InvalidArgumentException prevents the migration from being set back to STATUS_IDLE (line 287), resulting in a stuck migration at STATUS_IMPORTING.

Has anyone else seen these errors?

Multilingual Migrations for Non-Drupal Sources

$
0
0

Motivation

So there's a flurry of activity concerning multilingual Drupal content from D6 & D7 being properly migrated (#2208401: [META] Multilingual migrations / i18n meta issue), but I'm not seeing much if anything concerning non-Drupal imports for multilingual content. Point of fact, I'm having trouble coming up with good examples of how multilingual migrations are intended to work, let alone actual working examples using Drupal or other sources.

Proposed resolution

I'd like to use this thread to compile migration solutions or examples that successfully implement multilingual content. Ultimately, that would become a documentation page, or depending on how things go a feature request or module.

Groundwork

So since I had an immediate need and was looking for solutions I ended up finding #2313265: How import Multilingual Content with Migrate Module. While it originated Pre-D8, @digitaldonkey had a good solution for a POST_ROW_SAVE event in D8. I liked it, but it wasn't flexible enough for me to I took it and made it a little more broadly based. I updated the 'updateTranslations' function of the original:

/**
   * MigrateEvents::POST_ROW_SAVE event handler.
   *
   * @param MigratePostRowSaveEvent $event
   *   Instance of Drupal\migrate\Event\MigratePostRowSaveEvent.
   */
  public function updateTranslations(MigratePostRowSaveEvent $event) {

    $row =  $event->getRow();

    if ($row->hasSourceProperty('constants/available_languages')) {

      // These are defined in migration.yml.
      $available_languages = $row->getSource()['constants']['available_languages'];
      $default_language = $row->getDestination()['langcode'];

      // Unset default language from available languages.
      unset($available_languages[$default_language]);

      $migrated_entity = $event->destinationIdValues[0];
      $dest_config = $event->getMigration()->getDestinationConfiguration();
      $dest_plugin = explode(':', $dest_config['plugin']);

      if ($dest_plugin[0] == 'entity') {
        $entity = \Drupal::entityTypeManager()
          ->getStorage($dest_plugin[1])
          ->load($migrated_entity);

        foreach ($available_languages as $key => $lang_map) {

          $translated_entity = $entity->addTranslation($key);
          foreach ($lang_map as $field => $source) {
            $translated_entity->$field = $row->getSourceProperty($source);
          }
          $translated_entity->save();

        }

        $map = $event->getMigration()->getIdMap();
        $map->saveIdMapping($event->getRow(), array($migrated_entity));
      }
    }
  }

What this allows you to do is declare translations in your YAML file by adding available translations as constants. So your source would look something like

source:
  ...
  constants:
    available_languages:
      en:
      es:
        title: title_spanish

Where title is the name of the field you're entering and title_spanish would be the field coming in from the source. This is perfect for a lightweight translation of content from the same source. Note that it only works on entities and that the main langcode MUST be set in the process.

For bulkier translations that need processing or those coming from a different source, I put together a custom destination. This takes a separate migration and appends identically ID'd translations to it.


namespace Drupal\custom_migrate\Plugin\migrate\destination;

use Drupal\Component\Plugin\DependentPluginInterface;
use Drupal\Core\Entity\DependencyTrait;
use Drupal\migrate\Plugin\MigratePluginManager;
use Drupal\migrate\Plugin\MigrationPluginManagerInterface;
use Drupal\Core\Language\LanguageManagerInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Drupal\migrate\Plugin\MigrationInterface;
use Drupal\migrate\Row;
use Symfony\Component\DependencyInjection\ContainerInterface;
use Drupal\migrate\Plugin\migrate\destination\DestinationBase;

/**
 * Provides Configuration Management destination plugin.
 *
 * Persist data to the config system.
 *
 * When a property is NULL, the default is used unless the configuration option
 * 'store null' is set to TRUE.
 *
 * @MigrateDestination(
 *   id = "entity_translation"
 * )
 */
class EntityTranslation extends DestinationBase implements ContainerFactoryPluginInterface, DependentPluginInterface {

  use DependencyTrait;

  /**
   * The config object.
   *
   * @var \Drupal\migrate\Plugin\MigrationInterface
   */
  protected $old_migration;

  /**
   * The language manager.
   *
   * @var \Drupal\Core\Language\LanguageManagerInterface
   */
  protected $language_manager;

  /**
   * The process plugin manager.
   *
   * @var \Drupal\migrate\Plugin\MigratePluginManager
   */
  protected $processPluginManager;

  /**
   * The migration plugin manager.
   *
   * @var \Drupal\migrate\Plugin\MigrationPluginManagerInterface
   */
  protected $migrationPluginManager;

  /**
   * Constructs a Config destination object.
   *
   * @param array $configuration
   *   A configuration array containing information about the plugin instance.
   * @param string $plugin_id
   *   The plugin ID for the plugin instance.
   * @param mixed $plugin_definition
   *   The plugin implementation definition.
   * @param \Drupal\migrate\Plugin\MigrationInterface $migration
   *   The migration entity.
   * @param \Drupal\Core\Language\ConfigurableLanguageManagerInterface $language_manager
   *   The language manager.
   */
  public function __construct(array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration, MigrationPluginManagerInterface $migration_plugin_manager, MigratePluginManager $process_plugin_manager, LanguageManagerInterface $language_manager) {
    parent::__construct($configuration, $plugin_id, $plugin_definition, $migration);
    $this->migrationPluginManager = $migration_plugin_manager;
    $this->migration = $migration;
    $this->processPluginManager = $process_plugin_manager;
    $this->language_manager = $language_manager;
  }

  /**
   * {@inheritdoc}
   */
  public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition, MigrationInterface $migration = NULL) {
    return new static(
      $configuration,
      $plugin_id,
      $plugin_definition,
      $migration,
      $container->get('plugin.manager.migration'),
      $container->get('plugin.manager.migrate.process'),
      $container->get('language_manager')
    );
  }

  /**
   * {@inheritdoc}
   */
  public function import(Row $row, array $old_destination_id_values = array()) {

    $migration_id = $this->configuration['migration'];
    $migration = $this->migrationPluginManager->createInstance($migration_id);

    // TODO: I think this only works right now if the keys and key labels match, so I'll need to expand later
    $source_id_values = $row->getSourceIdValues();

    $destination_ids = $migration->getIdMap()->lookupDestinationID($source_id_values);

    $dest_config = $migration->getDestinationConfiguration();
    $dest_plugin = explode(':', $dest_config['plugin']);

    $entity = \Drupal::entityTypeManager()
      ->getStorage($dest_plugin[1])
      ->load($destination_ids[0]);

    $lang = $row->getDestinationProperty('langcode');

    // TODO: Validate langcode against list of site languages

    $translated_entity = $entity->addTranslation($lang, $row->getDestination());
    $translated_entity->save();

    return $destination_ids;

  }

  /**
   * {@inheritdoc}
   */
  public function fields(MigrationInterface $migration = NULL) {
    // @todo Dynamically fetch fields using Config Schema API.
  }

  /**
   * {@inheritdoc}
   */
  public function getIds() {
    $ids['config_name']['type'] = 'string';
    return $ids;
  }

  /**
   * {@inheritdoc}
   */
  public function calculateDependencies() {
    $provider = explode('.', $this->config->getName(), 2)[0];
    $this->addDependency('module', $provider);
    return $this->dependencies;
  }

}

It's still very rough, but once it's in place you can use it to translate entities by adding this destination:

destination:
  plugin: entity_translation
  migration: original_content

Where original_content is the targeted migration. Note that it's still very rough, but is certainly a step in the right direction. Once again, it will only work for entities and the langcode needs to be set in the process.


Re-create image and file field-like formatters on top of media entity

$
0
0

Problem/Motivation

With #2831274: Bring Media entity module to core as Media module and its bundles on core we'll have a powerful media system. After we figured out storage we'll need to do display/render part.

When a media entity is referenced from another piece of content we can use existing "Rendered entity" formatter.

Proposed resolution

First decide if "Rendered entity" formatter suffices for the use-case. If that will be the case provide default configuration that will re-create existing functionality with image and file fields and lead the way for site-builders and contrib.

If not plan and implement formatters for media entities that will re-create behavior of existing ones.

Remaining tasks

- decide about the approach
- create default configuration or new formatters

XSS::filter and filter_xss can create malformed attributes when you would expect them to be stripped

$
0
0

This was originally reported by alexpott to the Drupal Security Team, but is being made public since there is no actual vulnerability and it can be treated as a public bug.

There is no vulnerability since "on" attribute names are renamed which renders them harmless.

Problem/Motivation

Drupal\Component\Utility\Xss::filter has the following behaviour:

HEAD

BEFORE: <IMG SRC= onmouseover="alert('xxs')"
AFTER: <IMG nmouseover="alert(&#039;xxs&#039;)">

With patch

BEFORE: <IMG SRC= onmouseover="alert('xxs')"
AFTER: <IMG>

You can see the bug by running the test code below using "drush scr xss.php.txt"

<?php

$strings = [
  '<IMG SRC= onmouseover="alert(\'xxs\')"','<IMG onmouseover="alert(\'xxs\')"','<img src="http://example.com/foo.jpg" title="Example: title" alt="Example: alt">',
];

foreach ($strings as $original) {
  $string = filter_xss($original, array('img'));
  print "BEFORE: $original\nAFTER: $string\n\n";
}

Proposed resolution

Fix the logic so malformed attributes are stripped

Remaining tasks

review patch, backport.

User interface changes

n/a

API changes

n/a

Data model changes

n/a

Allow customization of stub rows from Migration process plugin

$
0
0

Problem/Motivation

When building migrations where the stub entity generated by the Migration process plugin may not be "filled in" for some time, you may want to tailor that stub to have some friendlier-than-alphanumeric scramble for site users. While the current option to set up a fallback for the stub to use (via the default_value plugin, for example), that is for largely static fallback values. If you want to use date from the content referencing the new stub as context for dynamic values, you need a way to manipulate the stub before the import is run.

Secondary use case: Your migrations are bundle-neutral, and you need that contextual data to derive the appropriate bundle.

Proposed resolution

As an edge case, leave this up to custom process plugins. However, the Migration plugin has one really large method doing 99% of the work, which is hostile to doing anything to manipulate the stubbing without duplicating code. Let's break this up into more discrete methods that can be overridden for custom migration stub processing.

Remaining tasks

Confirm direction, etc.

User interface changes

None.

API changes

More protected methods on migration plugin.

Data model changes

None.

.htaccess redirect to www.domain.com also redirects subdomains to www.subdomain.domain.com

$
0
0

Hi,

When enabling the redirect from domain.com to www.domain.com in the htaccess file, it will also redirect sub.domain.com to www.sub.domain.com . This is in general unintended behaviour and should be fixed (and I would also like a fix :))

Regards,

Geert

RevisionLogEntityTrait::getRevisionLogMessage displays a notice when no revision log message is set

$
0
0

Problem/Motivation

Notice: Trying to get property of non-object in Drupal\Core\Entity\RevisionableContentEntityBase->getRevisionLogMessage() (line 104 of /vagrant/app/core/lib/Drupal/Core/Entity/RevisionLogEntityTrait.php)

Proposed resolution

Return an empty string for missing log messages as per the interface:

  /**
   * Returns the entity revision log message.
   *
   * @return string
   *   The revision log message.
   */

Remaining tasks

User interface changes

API changes

Data model changes

Viewing all 297295 articles
Browse latest View live


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