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

Node revision revert behavior is weird when e.g. using paragraphs fields and can not altered

$
0
0

Problem/Motivation

When reverting a (node) revision, the user can chose between reverting only the translatable fields or all fields. While I'm still not happy about the whole kind-of-per-language revision UI, it's especially bad when using paragraphs or another embedded entity, I guess field_collection works basically the same way. IEF when using entity reference revision fields the same I guess.

1. If you chose to only revert this translation, then nothing happens, because the paragraph/reference field is not translatable and the whole field has been skipped.

2. If you revert all fields, then the the reference is reverted back to that old reference, which updates this translation but also reverts all translations back to that state, including deleting translations that were added after that.

Proposed resolution

Not sure, maybe add an event or hook, so that for example entity_reference_revisions can replicate what \Drupal\node\Form\NodeRevisionRevertTranslationForm::prepareRevertedRevision() did for any referenced paragraph.

Remaining tasks

User interface changes

API changes

Data model changes


Introduce a fallback system for untranslated strings to avoid breaking translations when a string only has minor edits

$
0
0

Problem/Motivation

Every time we change a translatable string in a Drupal release, we break translations of that string for all languages, until someone comes along and re-translated the string (if that ever even happens at all).

As a result, we are cautious about changing strings. In Drupal 8, it is only done in minor releases, i.e. every 6 months (see https://www.drupal.org/core/d8-allowed-changes#evaluate), whereas Drupal 7 core is relatively liberal about doing it for admin-facing strings but very conservative about doing it for end-user-facing strings (see https://www.drupal.org/node/1527558).

But if you think about it, in most cases it is ridiculous to break a site's existing translations just because we want to make a small improvement to the text. Here are a couple examples:

  1. Fixing a typo

    Suppose the original string looked like this:

    t('Hello, how are youu?')

    Oops, there's a typo - so once that is discovered we obviously want to fix it.

    In this case, there's no reason to assume that the translators introduced a typo in their own language when translating the string from English! So breaking translations makes absolutely no sense at all.

  2. Fixing a small bug or adding some minor clarification

    A real life example can be found at #2923151: Usernames allow @ symbol. There, a minor issue was identified with the user registration form's help text being slightly incorrect (it fails to tell people that the @ sign is allowed in usernames).

    In this case, the mistake would exist in other languages also, so we do want translators to re-translate the string eventually. However, before that happens, do we really want to show end users who don't speak any English the English version of the string? Of course not... it would be preferable for them to see something in their own language (even if it's slightly imperfect) than to see something in a language they don't understand at all.

Proposed resolution

Let's consider introducing a simple fallback system where a developer can pass in alternate strings to use for translation in case the main/preferred string doesn't have a translation available.

Conceptually, the easiest way to think of this is to allow t() to optionally accept an array of strings as its first parameter (instead of a single string).

So in that case, with the first example above, when we fix the typo, instead of just replacing the old string, we would change it to this:

t(array('Hello, how are you?', 'Hello, how are youu?'))

and the system would try to find a translation for the first string if available, but fall back on the second string's translation if not.

The second example above would be similar.

API changes

This is an API addition, not an API change.

However, it would be an API change for code like https://www.drupal.org/project/potx which needs to parse files and look for translatable strings in them. That module would need to be updated so that it recognizes code with this new pattern.

Unable to change non-translatable field value on translatable content with content moderation enabled.

$
0
0

Unable to change non-translatable field value on translatable content with content moderation enabled, because of EntityUntranslatableFieldsConstraintValidator::validate

To reproduce:
1) Install D8.5.0 with the standard profile in EN language.
2) Enable content moderation on Article node type.
3) Enable 'Content Translation' (with dependent Language) module.
3) Add another language.
4) Enable translation of Article content type at Configuration --> Content language and translation, set all fields translatable, except Tags.
5) On manage fields, disable 'Users may translate this field' for Tags field.
6) Add new Article node, with e.g. 'Test' tag and publish content.
7) Create new draft on the created node and change Tags field - e.g. delete 'Test' tag, or add another one.

You wouldn't be able to save the node because of validation error:
Non-translatable fields can only be changed when updating the current revision.

Solutions:
a) the EntityUntranslatableFieldsConstraintValidator::validate() should check if the content isModeratedEntity() or
b) content moderation module should extend EntityUntranslatableFieldsConstraintValidator::validate()

Add views render caching on views ajax requests.

$
0
0

Problem/Motivation

#2381277: Make Views use render caching and remove Views' own "output caching" replaces output caching with render caching.
Render caching though is disabled on POST requests, so that ajax requests aren't cacheable.

We need to get #956186: Allow AJAX to use GET requests in, to be able to get render caching done.

Proposed resolution

- Add setting for query type to views pagers
- Make views pager respect that setting so that it uses the correct protocol
- Get render caching to work on views AJAX paging responses

Remaining tasks

- Fix broken tests on 8.3 re-roll.
- Get #956186: Allow AJAX to use GET requests committed
- Verify that we have enough test coverage on this issue
- QA testing to get to RBTC

User interface changes

I added a "pager query type" selector to sql-base pagers which becomes active if you set the view to use AJAX.

API changes

- Added a "getParam" method to ViewAjaxController to make it easier to get parameters off of a request.

How to test

- Install a new site
- Apply most recent patch from this issue (currently: https://www.drupal.org/files/issues/2500313--views-get-paging-support-83...)
- Apply https://www.drupal.org/files/issues/ajax-956186-65_2x_1.patch from #956186: Allow AJAX to use GET requests
- Create at least five articles
- Create two views as follows

View 1
- Add a block display
- Call it "GET pager view"
- List all nodes
- Turn on AJAX for the view
- Use a pager (try them all if you can); 2 per page, set query type to GET

View 2
Same as View 1, except:
- Call it "POST pager view"
- Set query type on the pager settings to POST

Now:
- Place both blocks somewhere on the page
- Start using the pager, and use the network tab (helpful to filter by XHR) to ensure that the views are using the correct protocol for their requests.

Some other things to try:
- Using a table display, ensure that column sorting is respected after paging back and forth.
- Add an exposed filter and make sure paging works after the setting the filter value.
- Test the render caching somehow. Make sure page cache is turned on, and put a breakpoint or something inside a function that runs when rendering a row. The breakpoint should hit a) when the cache is first populated and b) if something invalidates the cache (i.e. that node is updated).

Views Date Filter Datetime Granularity Option

$
0
0

Problem/Motivation

1. Create a content type with a Datetime field
2. Create some sample data with the content type
3. Create a simple view that has one exposed filter for selecting the Date
4. The exposed filter will force you on the 'is equal to' operator to make an exact match on specific datetime fields prior to listing

Cases:
1. Site allows users to create specific meeting times but the client wants search by month or day
2. Views does not allow the user to select the granularity of the search against the Datetime field, you can select the between operator, however if you have separate start/end dates it becomes more complicated since you would have to have the operator work between 4 specific dates... ugh.

Proposed resolution

Add simple form element to date exposed filter to allow the user to select the granularity of their date input
Date Filter 1
Date Filter 2

Remaining tasks

User interface changes

Add a new form element to the views exposed filter

API changes

Data model changes

Original report by generalconsensus

Allow override the menu link titles at core.menu.static_menu_link_overrides.yml

$
0
0

Using the Menu UI page we can override some values of the menu links provided by modules, Those values are:

  • menu_name
  • parent
  • weight
  • expanded
  • enabled

But one important value is missing, the "title" field, I don't know if there is a technical reason why the title isn't overridable but seems something which might be useful, for instance #2838106: Standard profile: make "Home" menu link to <front> editable/deletable giving the user the ability to just edit the title would fix that issue and the same happens for any menu link provided by a contrib module.

In my next comment a patch with the change.

(This will require tests which I can provide as well but I just want to know first if there is a reason why the title wasn't between these values in first place I just fixed the tests to include this new key, so not sure if we need more tests.)

The Views integration Datetime Range fields should extend the views integration for regular Datetime fields

$
0
0

Follow-up to #2161337: Add a Date Range field type with support for end date

Problem/Motivation

datetime_field_views_data() performs some nice improvements for the Views integration for datetime fields, but has not yet been updated to cover daterange fields, so daterange fields only receive the integration provided by the views_field_default_views_data() fallback. This means that for example, the year-only, month-only, etc. formats aren't available as arguments for daterange fields like they are for datetime fields.

Proposed resolution

The proposed resolution is to allow datetime views plugin to be used for datetime_range fields too. Together with this we have to make sure: extending/reusing the current datetime implementation becomes an easy task for developers, any existing views making use of datetime_range fields is correctly updated, default views shipped with contrib modules using old plugins are automatically migrated on save, etc.
In order to achieve that the solution should include the following tasks:

  • Extending the datetime fields Views integration in order to allow any datetime-based fields to make use of it. #4
  • Letting daterange fields use the same Views integration capabilities that datetime fields have, using the work from previous point. #4
  • Providing an upgrade path for views having old datetime_range fields string/standard views plugins to new plugins types. #24 ~ #139
  • Updating contrib modules provided views having old datetime_range fields string/standard to new plugins types. #133 ~ #142

Remaining tasks

  • map current 'string' view plugin values/operators to new 'datetime' plugin on the update path using regular_expression operator
  • take care of contrib views too. Move all the existing update logic to hook_view_presave and just do $view->save() in the update hook when appropriate as described in #133
  • update path test for #127 and #129 changes
  • Convert Webtestbase based testing to Browsertestbase
  • Deciding if we need a stronger message alerting the user to manually review the views being converted (and/or may be a Change record?). Change Record added.
  • Update the issue summary:
    • User interface changes: the IS should mention this issue is neither adding nor removing UI elements, instead we are moving from string/standard views plugins UI to datetime ones. A screenshot with "before - after" should help.
    • API changes: "Extending the datetime fields Views integration in order to allow any datetime-based fields to make use of it" solution task introduce a new API helper for datetime-based fields who want to integrate datetime views plugins easily.
    • Data model: we are not changing any data model. However existing and contrib modules shipped views may be altered. Developers and site builders should be aware of that.

  • UI/API/Data Model changes above need a place in the CR - together with a good clean up - as flagged by #192.7
  • Upgrade test path is still using old simpletest. We should move it to use Drupal\FunctionalTests\Update\UpdatePathTestBase

User interface changes

This issue doesn't introduce new UI elements, but it converts Views filter and sort plugins from string/standard formats to datetime based ones. The change is automatic, site-builders and developers don't need to do any action.
See the example below of how the UI will change for a Views filter plugin against a datetime_range field:
Before:
before
After:
before

API changes

datetime_type_field_views_data_helper - new API helper to integrate datetime views plugins easily for any datetime-based fields. Modules defying datetime-based fields can now benefit of datetime Views plugins easily.

Example usage in core/modules/datetime_range/datetime_range.views.inc:

/**
 * Implements hook_field_views_data().
 */
function datetime_range_field_views_data(FieldStorageConfigInterface $field_storage) {
  \Drupal::moduleHandler()->loadInclude('datetime', 'inc', 'datetime.views');

  // Get datetime field data for value and end_value.
  $data = datetime_type_field_views_data_helper($field_storage, [], 'value');
  $data = datetime_type_field_views_data_helper($field_storage, $data, 'end_value');

  return $data;
}

Data model changes

There are no Data model changes. However existing and contrib modules' shipped Views - using datetime_range fields/plugins - may be altered. See update message about the ids of changed views like (view id is datetime_test):
update info

The update will map existing datetime_range views string plugins operators/values according with this list:

  • = maps to =, value is unchanged
  • != maps to !=, value is unchanged
  • not maps to !=, value is unchanged
  • starts maps to regular_expression, value is prefixed with '^'
  • ends maps to regular_expression, value is suffixed with '$'
  • any other operator (contains, word, allwords, not_starts, not_ends, shorterthan, longerthan, regular_expression) maps to regular_expression, value is unchanged if not empty otherwise *. is used

Example, filter Starts with with 'value' will be converted into Regualr expression with '^value';

Allow to specify a different database URL in the dev-site command


Path alias filter by system path

$
0
0

Problem/Motivation

Currently core's Path modules allows to filter url aliases only by alias itself. It is often required to filter by system path, instead of alias.

The only solution I use is to query database directly, which is very inconvenient.

Proposed resolution

Add a filter for system path.

Remaining tasks

User interface changes

New filter

API changes

N/A

Data model changes

N/a

Class active-trail not added to li element when linking to front page

$
0
0

There is a bug with the "active-trail" class not showing up on <li> for menu items with Drupal 7.14. The problem is that "active-trail" is missing for a menu link to the front page (path "<front>"), all other links have "active-trail" just fine.

The situation is also slightly different for the horizontal primary link tabs that can be switched on from theme settings Toggle display - Main menu, than they are for the vertical navigation in the Main menu block. In the horizontal tabs the front page <li> has "active" but not "active-trail". So "active" could be used to do get around this issue for horizontal menus. But unfortunately if you want the vertical menu, there is no "active" nor "active-trail".

I verified that both "active" and "active-trail" are missing with a fresh install without any added modules on Drupal 7.4 to 7.14. The behaviour is identical with Bartik, Garland and Stark themes, as well as Zen.

Steps to reproduce:

1. Create a fresh install of Drupal 7.14.
2. On the front page go to Structure -> Blocks.
3. Move "Main menu" block to "First sidebar"
4. Create a new "Basic page" with test content and click "Provide a menu link" -> "Parent item" [Main menu]
5. Use e.g. Firebug to verify that the newly created test page link on the sidebar has "active-trail" on <li> but "Home" does not.

Attached is a patch that fixes the bug by adding special handling for the front page when adding the active-trail class. A better solution would be to get the 'in_active_trail' variable correctly set for links to <front>, but unfortunately I could not find out how to do that.

Modify Layout Builder's use of the off-canvas tray to improve UX of larger block forms

$
0
0

The Layout Builder uses core's off-canvas "tray" when adding/editing blocks to a layout. It opens the tray on the right side of the page, but it's not very wide, and as a result it doesn't accommodate larger block forms very well. This is most evident when adding block that has a textarea field w/ CKEditor:

ckeditor tray

This problem surfaced in #2948064: Layout Builder should support inline creation of Custom Blocks.

An interesting issue to follow that may help resolve this is #2916781: Allow off-canvas dialog to be rendered elsewhere on the page.

Sort image style configuration

$
0
0

Problem/Motivation

Image style configuration can have sorting issues that result in configuration diffs that have unnecessary changes.

Proposed resolution

Sort effects using the new schema sorting.

Remaining tasks

User interface changes

None

API changes

None

Data model changes

Image style config sorted correctly - will need a post update to resave image config to fix this.

Does theme('username',...) support absolute path?

$
0
0

I read that theme('username',...) should be used with Real Name to pull the username.
Does it also support rendering the absolute path to show the full site url?

In my emails the site url is missing thus link don't work. I already tried including "'absolute' => TRUE".

Example form FAQ Module:
'creator' => theme('username', array('account' => user_load($node->uid), 'plain' => TRUE, 'absolute' => TRUE)),

http://cgit.drupalcode.org/faq_ask/tree/faq_ask.module?id=9f4fbb7859c8fc...

Fixes for MigrateUpgradeForm

$
0
0

Postponed on #2687843: Add back incremental migrations through the UI

Problem/Motivation

A review of the patch in #2687843: Add back incremental migrations through the UI comment #98 included some points that were outside the scope of the issue and need to be addressed.

The relevant is in comment#99

This is a copy of the points to be addressed in this issue

2.    +++ b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php
    @@ -236,6 +244,51 @@ public function submitOverviewForm(array &$form, FormStateInterface $form_state)
    +    $database_state_key = $this->state->get('migrate.fallback_state_key', '');
    +    if ($database_state_key) {

    Why would we use the fallback state key here? The user has entered explicit database credentials here, so I don't understand why we wouldn't just use those.

3.    +++ b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php
    @@ -236,6 +244,51 @@ public function submitOverviewForm(array &$form, FormStateInterface $form_state)
    +      $form_state->setValue('step', 'credentials');
    +      $form_state->setRebuild();

    Nit: setValue() is chainable, so we could do ->setValue()->setRebuild().

4.    +++ b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php
    @@ -848,6 +877,44 @@ protected function getDatabaseTypes() {
    +   * Setup migrations.
    +   *
    +   * @param array $database
    +   *   Database array representing the source Drupal database.
    +   * @param \Drupal\Core\Form\FormStateInterface $form_state
    +   *   The current state of the form.
    +   */
    +  protected function setupMigrations(array $database, FormStateInterface $form_state) {

    Can this doc comment be expanded a bit? "Setup migrations" tells me nothing more than the method name already does.

5.    +++ b/core/modules/migrate_drupal_ui/src/Form/MigrateUpgradeForm.php
    @@ -848,6 +877,44 @@ protected function getDatabaseTypes() {
    +    $form_state->set('version', $version);
    +    $form_state->set('migrations', $migration_array);

    Nit: ->set() is chainable.

10.     +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php
    @@ -315,4 +281,110 @@ protected function translatePostValues(array $values) {
    +   * @param $session
    +   *   The currenct session.

    $session needs a type hint (also in the method signature), and there's a typo in 'current'.

11.    +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php
    @@ -315,4 +281,110 @@ protected function translatePostValues(array $values) {
    +   * @param $session
    +   *   The currenct session.
    +   */
    +  protected function assertIdConflict($session) {

    $session needs to be type hinted, and 'current' is misspelled. :)

12.    +++ b/core/modules/migrate_drupal_ui/tests/src/Functional/MigrateUpgradeTestBase.php
    @@ -315,4 +281,110 @@ protected function translatePostValues(array $values) {
    +    // Have to reset all the statics after migration to ensure entities are

    'statics' should be 'static caches'.

Proposed resolution

Respond to the feedback

Remaining tasks

This will needs a patch, a review etc.

Add stream wrappers to access extension files

$
0
0

Problem/Motivation

Starting from #2351919: Replace uses of drupal_get_path() with __DIR__ where possible, when the PHP code needs to include or parse files inside the module or theme directory space, will simply use _DIR_ instead of drupal_get_path(). This is sufficient, intuitive and more performant than calling drupal_get_path().

However, drupal_get_path() is widely used to refer files (.js, .css, images, assets) outside a module or theme. This isn't very intuitive for new developers. Stream wrappers make much more sense and simplify the API for developers trying to refer directories or files from outside the current extension in code.

Proposed resolution

Introduce extension stream wrappers:

SchemeDescription
profile://Points to the installed profile root directory.
module://{name}Points to the module {name} root directory. Only enabled modules can be referred.
theme://{name}Points to the theme {name} root directory. Only installed themes can be referred.

Examples

Profile: profile://

Assuming the standard profile is installed:

  • Referring a directory:
    • Actual: drupal_get_path('profile', 'standard') . '/config'
    • Proposed: profile://config
    • Path: core/profiles/standard/config
  • Referring a file:
    • Actual: drupal_get_path('profile', 'standard') . '/config/install/automated_cron.settings.yml'
    • Proposed: profile://config/install/automated_cron.settings.yml
    • Path: core/profiles/standard/config/install/automated_cron.settings.yml

Module: module://

Assuming the node module is enabled but color module is not:

  • Referring a directory:
    • Actual: drupal_get_path('module', 'node') . '/config'
    • Proposed: module://node/config
    • Path: core/modules/node/config
  • Referring a file:
    • Actual: drupal_get_path('module', 'node') . '/config/install/node.settings.yml'
    • Proposed: module://node/config/install/node.settings.yml
    • Path: core/modules/node/config/install/node.settings.yml
  • Referring a resource in a uninstalled or inexistent module:
    • Actual: drupal_get_path('module', 'color') . '/config'
    • Proposed: module://color/config
    • Path: Throws \RuntimeException

Theme: theme://

Assuming the bartik theme is installed but seven theme is not:

  • Referring a directory
    • Actual: drupal_get_path('theme', 'bartik') . '/config'
    • Proposed: theme://bartik/config
    • Path: core/themes/bartik/config
  • Referring a file
    • Actual: drupal_get_path('theme', 'bartik') . '/color/color.inc'
    • Proposed: theme://bartik/color/color.inc
    • Path: core/themes/bartik/color/color.inc
  • Referring a resource in a uninstalled or inexistent theme:
    • Actual: drupal_get_path('theme', 'seven') . '/config'
    • Proposed: theme://seven/config
    • Path: Throws \RuntimeException

Remaining tasks

None.

API changes

New abstract class for extensions stream wrappers:

  • \Drupal\Core\StreamWrapper\ExtensionStreamBase

New stream wrapper classes:

  • \Drupal\Core\StreamWrapper\ModuleStream
  • \Drupal\Core\StreamWrapper\ThemeStream
  • \Drupal\Core\StreamWrapper\ProfileStream

Data model changes

None.


php errors triggered during search indexing if content contains broken internal links

$
0
0

Updated: Comment #26

Problem/Motivation

Search indexing of nodes in Drupal 7 and earlier versions considers incoming links. In the process, however, it can trigger PHP notices if a node contains a link to a non-existing node:

Notice: Trying to get property of non-object in search_index() (line 640 of (...)/modules/search/search.module).

Proposed resolution

Before trying to add the node ID to the links table, check to see that the query that returned the node ID returned a result.

Remaining tasks

There is a patch with a test. Ready to commit.

User interface changes

None, except that an error will not be triggered.

API changes

None.

Original report by deastlack

purging error log prior to running cron
cron spews dozens of the following error message:

Warning: Cannot modify header information - headers already sent by (output started at /mnt/data/www-dev/sites/drupal7/charity.org/trunk/includes/common.inc:2567) in drupal_send_headers() (line 1022 of /mnt/data/www-dev/sites/drupal7/charity.org/trunk/includes/bootstrap.inc).

Warning: is_dir(): Unable to find the wrapper "flickr" - did you forget to enable it when you configured PHP? in file_prepare_directory() (line 444 of /mnt/data/www-dev/sites/drupal7/charity.org/trunk/includes/file.inc).

Notice: Trying to get property of non-object in search_index() (line 640 of /mnt/data/www-dev/sites/drupal7/charity.org/trunk/modules/search/search.module).

unable to find any clues to resolve this situation.

Any thoughts are appreciated.

[PP-1] Refactor theme hooks/registry into plugin managers

$
0
0

Currently blocked on #2954562: [PP-1] Create provider type based plugin managers

Problem/Motivation

Most of the effort in 8.x to "update the theme system" was focused primarily around converting everything to Twig.

While this is all well and good, Twig is ultimately the last step in the "theming" process.

We really didn't touch a lot of the theme system internals, just moved them around a bit into other OO classes/services.

We're still using antiquated hooks to define the theme registry and templates it may provide.

It's time we modernize it using existing systems.

See #2863819-22: Convert theme hooks (defined by hook_theme()) to be objects for more discussion regarding this topic.

Proposed resolution

Create two new annotated plugins/manangers:

  • @Theme - Used to define a theme and handle the preprocessing/rendering.
  • @Template - Actual template definitions (formerly known as "theme hooks" provided by hook_theme())

An example in contrib (still a WIP):
https://cgit.drupalcode.org/plus/tree/src/ThemePluginManager.php?h=8.x-4.x

Remaining tasks

TBD

User interface changes

TBD

API changes

TBD

Data model changes

TBD

Update README.txt to drupal preferred format

Drupal dialog form buttons not allowing ampersands

$
0
0

Kind of an odd issue I've run into a bunch and decided it's a bigger deal than a mistake on my part.

It's related to the prepareDialogButtons method in the dialog.ajax.js file.

Because it calls $.html() instead of .text(), if you put an ampersand in a a.button's inner html, the ampersand will be escaped.

I understand why we call .html(), but I am coming up with a solution to fix this.

Reproduce the issue by loading a form into a dialog, and having one of the form's action buttons (a.button) be have a ampersand.

No ability to control "extra fields" with Layout Builder

$
0
0

Problem/Motivation

When using a layout for a node that has content moderation enabled, the form for moderating content is output outside of the layout, which is an issue from a theming perspective if the intent was to allow the layout to control where wrappers are placed.

Layout Builder allows manipulating all fields of an entity by providing a block for each.
However, it ignores all "extra fields" defined by hook_entity_extra_field_info()

Proposed resolution

Write a block plugin deriver that processes extra fields
Figure out a way to render them (since they are usually rendered in hook_entity_view_alter())
Keep an eye on https://www.drupal.org/project/extra_field as a possible solution

Remaining tasks

N/A

User interface changes

N/A

API changes

N/A

Data model changes

N/A

Viewing all 300213 articles
Browse latest View live


Latest Images

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