Account created on 8 May 2013, over 11 years ago
#

Merge Requests

More

Recent comments

🇦🇹Austria mvonfrie

Changes are made on on 11.x (our main development branch) first, and are then back ported as needed according to our policies.

Of course, but in my opinion it still makes sense to report the version I observed it and then you change it as needed. Maybe due to other changes the problem doesn't exist anymore in 11.x.

🇦🇹Austria mvonfrie

@cilefen, for simpler steps just skip installing the group modile and modify the views.view.media view in a similar manner.

Why is this a bug and not a feature request?

Because when I change one view (or a config entity in general) I don't expect another virw config entity to be modified with the same change. And there are even cases where having different labels (or other values) for the same field on different displays are needed, i. e. a table display with abbreviations for column labels vs. full name for a grid display.

And why is a translation context needed?

Because otherwise all translations with the same value will get changed. The group module's group members view doesn't show insider scoped roles as user inherits from a global Drupal role he has but just manually assigned group roles (there's an issue for that, no need to discuss it here). To circumvent this until a fix is available I've added a column with the (global) Drupal roles and changed the label translation (German) of the other column to "Gruppen-Rollen". Then I noticed that the page title of admin/people/roles changed to "Gruppen-Rollen" as well.

🇦🇹Austria mvonfrie

For documentation purposes, to help others with the same problem finding the solution: today I asked for help on Slack and @kristiaanvandeneynde pointed me to this issue while he was working on the hotfix release.

@mvonfrie
As site administrator and group administrator, on the group contents view, I see the action "Add existing content" but not the action "Add new content". The user has all available permissions on the group. I found that the add existing content route requires _group_relationship_create_any_access while the add new content route requires _group_relationship_create_any_entity_access. And the corresponding access checks return different results: Drupal\group\Access\GroupRelationshipCreateAnyAccessCheck returns allow while Drupal\group\Access\GroupRelationshipCreateAnyEntityAccessCheck returns neutral.
What am I missing? Drupal is 10.3.8 and group is 3.3.0.

@kristiaanvandeneynde
Do you have group_support_revisions enabled?

@mvonfrie
Yes.
BTW, I have a similar problem with the "Add member" action on the group members view. The access result is neutral as well.

🇦🇹Austria mvonfrie

This is similar to Display implicit roles of group memberships Active , you must not assign insider/outsider roles, but it should be visible that the user implicitely "has" these roles.

🇦🇹Austria mvonfrie

Thanks, that seems to work. At least when debugging the SynchronizedGroupPermissionCalculator the calculated permissions look correct.

But still, the information about the implicit (outsider, insider, inherited) roles is missing. I will create a follow-up issue as feature request.

🇦🇹Austria mvonfrie

I stumbled upon this issue when executing a migration from a Drupal 7 site with organic groups which I implemented several months ago and the new site is almost ready for production now. I changed my plugin to filter out all non-individual roles from the mapping and that works. But I observe a strange behavior related to this and would like to ask if that is intended or not.

The Drupal 7 site has an og level "Author" role, which now is a global "Author" role with outsider and insider mappings for the group type. Users, organic groups and almost all contents get migrated from Drupal 7, except migrating the og-level roles to corresponding global roles. The admins have to do this manually. After running the migration I have the following in Drupal 10:

  • User A created
  • Group B created, Insider "Author" role bound to the global "Author" role is defined.
  • Membership of user A in group B created

Now when I assign the global "Author" role to user A, I nowhere see that it also got the "Author (insider)" role in group B implicitely assigned. Neither in the group members view, nor as read-only information in the group membership edit form. How can I check whether the outsider/insider scoped group roles actually are assigned?

🇦🇹Austria mvonfrie

I'm getting the exact same error on the admin page admin/reports/updates/settings.

🇦🇹Austria mvonfrie

Instead of fully disabling/uninstalling Big Pipe it also works to disable it just for the affected blocks (if that is deterministic). in my case I just disabled it for all views blocks:

/**
 * Implements hook_block_build_BASE_BLOCK_ID_alter().
 */
function mymodule_block_build_views_block_alter(array &$build, \Drupal\Core\Block\BlockPluginInterface $block) {
  // Disable placeholdering of this block.
  // @todo Remove this when "big_pipe sometimes fails to load blocks" is solved. See: https://www.drupal.org/project/drupal/issues/3390178#comment-15742673
  $build['#create_placeholder'] = FALSE;
}
🇦🇹Austria mvonfrie

Hello, I am facing same issue as well. On 10.3.1 with Group 3.2.2 I have a view which shows group contents of a given group (via contextual filter). The view page works fine, the view block (limited to 10 nodes) rendered on the group page doesn't show, there is just the BigPipe placeholder. When disabling Big Pipe the block is rendered correctly. This is for admin user. I cannot provide information for anonymous user as I haven't configured group permissions for that yet.

🇦🇹Austria mvonfrie

Using Core 10.3.1, Group 3.2.2 and Flexible Permissions 1.10, I repeatedly but not really reproducable get the following (unhandled) errors:

Symfony\Component\DependencyInjection\Exception\ServiceCircularReferenceException: Circular reference detected for service "group.anonymous_user_response_subscriber", path: "group.anonymous_user_response_subscriber -> group_permission.calculator -> flexible_permissions.chain_calculator". in Drupal\Component\DependencyInjection\Container->get() (Zeile 149 in /var/www/html/web/core/lib/Drupal/Component/DependencyInjection/Container.php)

TypeError: Drupal\flexible_permissions\ChainPermissionCalculator::__construct(): Argument #1 ($cache) must be of type Drupal\variationcache\Cache\VariationCacheInterface, Drupal\Core\Cache\VariationCache given, called in /var/www/html/web/core/lib/Drupal/Component/DependencyInjection/Container.php on line 261 in Drupal\flexible_permissions\ChainPermissionCalculator->__construct() (Zeile 63 in /var/www/html/web/modules/contrib/flexible_permissions/src/ChainPermissionCalculator.php).

They always appear together in the logs.

Maybe they will be resolved when upgrading to Flexible Permissions V2? If not please let me know to open a separate issue.

🇦🇹Austria mvonfrie

Addition: I had this problem already with 1.1.3 but just updated to 1.2.1 to check if it is still there.

🇦🇹Austria mvonfrie

I understand that Gin should care only about core as there are tons of contrib modules which might need to adapt themselves to Gin as well, which would bloat the module to handle all or even many of them. On the other hand, should all those contrib modules be aware of Gin and maybe other themes which need adjustments of he modules to work with them? That's the same problem just from the other side.

What about a more generic approach, like the Gin everywhere module does? It even enables Gin for some core forms which are not covered by Gin itself (Block Content, Media, Menu). Why not integrating Gin everywhere completely into Gin?

And additionally, please document it better how to enable Gin for your own custom entity type. At least put a section in the project documentation which points to the proper hooks in the gin.api.php. Thanks.

🇦🇹Austria mvonfrie

Why is your first example <a href="#">&nbsp;</a> (obviously) wrong? Syntactically it is totally correct, but of course semantically this doesn't make sense because the user will never be able to click this link. If this for some reason is used as a trap link (kind of honeypot) with a special url, you would know that the link has been "clicked"/followed by a robot and not a human, then it makes sense again.

Would be interesting what CKeditor5 does with this? <a name="top">&nbsp;</a> This is an invisible anchor which can be used as jump target (a "Top" button at the end of the page or floating at the bottom to jump back to the start of the page (after header, banner image etc.).

In my opinion, CKeditor5 should correct syntactically wrong markup but not interpret syntactically correct markup which maybe makes no sense, as it cannot know a developer's intentions.

🇦🇹Austria mvonfrie

@wotnak, at first not but then I created a file with simple test code. No change.

But I've skipped this approach due to other problems with Vite itself. Read https://www.drupal.org/project/vite/issues/3349311#comment-15657697 📌 Example configurations/starting points Active to see how I configured it for now.

🇦🇹Austria mvonfrie

I found a solution using Yarn workspaces. In addition I'm using Typescript.

In each module/theme you need the following files:

package.json
Eventually it makes sense to remove a common prefix from [module_or_theme_name] in the package.json. If i.e. all modules start with myproject_ like myproject_ui I would name the package @myproject/ui. The package names just need to be unique though.

{
  "name": "@myproject/[module_or_theme_name]",
  "type": "module",
  "engines": {
    "node": "^20.14",
    "yarn": "^4.3"
  },
  "private": true,
  "scripts": {
    "dev": "vite",
    "build": "tsc && vite build"
  },
  "devDependencies": {
    "@rollup/plugin-node-resolve": "^15.2.3",
    "@types/node": "^20.14.8",
    "fast-glob": "^3.3.2",
    "typescript": "^5.2.2",
    "vite": "^5.3.1"
  }
}

vite.config.ts

in the vite config the server part is important, so we skip the rest of the file here for simplicity:

export default defineConfig({
  server: {
    host: true, // "Set this to 0.0.0.0 or true to listen on all addresses, including LAN and public addresses." --> Needed for DDEV.
    port: xyz, // Every module/theme needs its own port, and all of them must be exposed from DDEV or Docker in general. We start with the default port 5173.
    strictPort: true // Ensure that every module/theme uses it's own port. "Set to true to exit if port is already in use, instead of automatically trying the next available port." --> If something doesn't work/some ports are already in use lets fail here as our dev servers would not be reachable.
  }
})

tsconfig.json
The tsconfig file for the module/theme (Vite application). To not duplicate all the settings, compiler options etc. we extend it from a base tsconfig in the project root.

Here the important part is the includes.

{
  "extends": "../../../../tsconfig.base",
  "include": [
    "components/**/*",
    "src/**/*"
  ],
  "references": [
    {
      "path": "tsconfig.node.json"
    }
  ]
}

tsconfig.node.json
The tsconfig file for the Vite config compilation step (this is only using for compiling the vite.config.ts).

{
  "compilerOptions": {
    "composite": true,
    "module": "ESNext",
    "moduleResolution": "Node",
    "allowSyntheticDefaultImports": true
  },
  "include": ["vite.config.ts"]
}

Root package.json
The Yarn workspace definition.

{
  "name": "@myproject/workspace",
  "type": "module",
  "packageManager": "yarn@4.3.0",
  "engines": {
    "node": "^20.14",
    "yarn": "^4.3"
  },
  "private": true,
  "scripts": {
    "dev": "yarn workspaces foreach -Rpi --topological-dev --from '@myproject/*' run dev",
    "build": "yarn workspaces foreach -Rp --topological-dev --from '@myproject/*' run build"
  },
  "workspaces": [
    "web/modules/custom/*",
    "web/themes/custom/*"
  ]
}

In the global dev and build scripts we run the corresponding scripts of all workspaces recursively (-R) in parallel (-p). We restrict them to a scope (--from '@myproject/*', the root package will be automatically excluded as Yarn detects that it would lead to an endless recursion). With --topological-dev Yarn will only run the command after all workspaces that it depends on through the dependencies and devDependencies field have successfully finished executing. This way the themes for example can depend on any of the modules.

In the dev script we additionally print the lines from the output as it receives them with the -i option. Without it (as in the build script) Yarn buffer the output from each process and print the resulting buffers only after their source processes have exited which makes more sense for scripts executed by a CI pipeline for example.

🇦🇹Austria mvonfrie

@ChrisScrumping I have a working webpack configuration in other projects. What I don't like with webpack is, that it builds dev and prod outputs into the same folder & files, which often leads to stupid git diffs (especially during development, even if you don't commit the changes). When you commit only prod builds, during development almost all generated files appear as changed because for prod they get minified and for dev not.

Of course there should be a configuration to create dist/style.css as non-minified during dev and prod build and an additional dist/style.min.css during prod build. But then still you do not have solved the issue which file Drupal should take (style.css or style.min.css) right now because the library definition is static. This is where the Vite module comes in very handy.

And integrating webpack with storybook might be another topic...

🇦🇹Austria mvonfrie

I spent over 8 hours to get Vite working in the project root. It is not possible, at least not yet. Maybe it will be in the future with the new Vite 6 Environment API.

<root> means the Vite project root, not the Drupal one. By default Vite generates the output in a dist folder, which would be in <root>/dist/. Even if I change it to <root>/web/dist/ to have the generated files in Drupal's web-root I have no chance to get the files where they need to be (<root>/web/[modules|themes]/custom/[module_name|theme_name]/dist/) as output.entryFileNames, output.assetFileNames etc. must not contain ../ to get out of the dist folder.

error during build:
Invalid pattern "../themes/custom/theme_name/components/title/style" for "output.entryFileNames", patterns can be neither absolute nor relative paths. If you want your files to be stored in a subdirectory, write its name without a leading slash like this: subdirectory/pattern.

🇦🇹Austria mvonfrie

The documentation regarding the Vite configuration example needs to be updated as well.

* in `<theme>/vite.config.ts`:

```diff
 import { defineConfig } from "vite"
 import multiInput from "rollup-plugin-multi-input"

 export default defineConfig({
   plugins: [multiInput.default()],
   build: {
     manifest: true,
     rollupOptions: {
       input: [
         [...]
+        "components/**/*.pcss.css",
+        "components/**/*.ts",
       ],
     },
   },
   [...]
 })
```

The import multiInput from "rollup-plugin-multi-input" and then loading the plugin with multiInput.default() no longer works for me> I'm getting the following error:

You must supply options.input to rollup

If I change this to multiInput() as in the examples from the rollup-plugin-multi-input repo itself, I get another error:

failed to load config from /var/www/html/vite.config.js
error during build:
TypeError: multiInput is not a function

I don't have a solution for this yet.

Version info:

Node 18.20 or 20.14.8
Yarn: 4.3.0
Vite: 5.3.1
Typescript: 5.2.2
rollup-plugin-multi-input: 1.4.1

🇦🇹Austria mvonfrie

@ChrisScrumping even if your module is not up to date, it still looks helpful. What I'm trying to achieve at the moment is a Drupal site with two themes and one module all using Vite together. That would mean having vite.config.js in the repo root instead of the theme's or module's folder, especially as it would be much easier to run only a single Vite dev server and not multiple ones in DDEV.

🇦🇹Austria mvonfrie

+1 for me as well.

I have similar use cases as @joachim.

My first use case is developing a migration from D7 Scald (using the migrate_source_scald_atom source which is completely undocumented and drush migrate:fields-source not really a help) to D10 Media.

My second use case is migrating user memberships from D7 organic groups to D10 groups, but I can't migrate the organic groups to groups as well. So I have to write a custom source plugin which reads the membership relations from the D7 database together with the D10 group UUIDs which will be added in the D7 instance. It is a bit too complicated to explain why we can't migrate organic groups to groups, lets simply say there are too big structural changes and the customer decided to use the migration to implement organizational changes already existing in real-life as well.

For both use cases it is really helpful to have a destination which doesn't create any data in the site until the plugins and migrations are ready and the real destination plugins can be used.

🇦🇹Austria mvonfrie

@Jaypan, that sounds legit. More helpful would be a proper documentation with examples how to do things (adding, removing, ...) subgroups correctly via API.

🇦🇹Austria mvonfrie

I found a lot of code depending on the system.mail configuration which is not used by Symfony Mailer, especially in the WebformEmailProvider class. This needs to be adapted by a check whether Symfony Mailer is active (and then an alternative implementation utilizing Symfony Mailer) or if it should use the old system.

There might be changes in the Symfony Mailer module needed as well, I've linked the one which I found.

🇦🇹Austria mvonfrie
$parent_entity = $this->entityTypeManager->getHandler('group', 'subgroup')->getParent($child_entity);

doesn't work for me. It throws MalformedLeafExceptions, at least for subgroups added programmatically.

🇦🇹Austria mvonfrie

Addition: Removing the recipients to prevent sending updates was the only way when Drupal used swiftmailer, as the update manager only has two options for the email notification threshold: all updates or only security updates, but no option to not send a notification.

After applying the MR on my site and looking into the policy I found the "skip sending" adjuster which is the correct way of not sending notifications on the test environment. But still there might be other use cases where the recipients are evaluated dynamically (or defined by users) and can be none, so the code still should handle that properly.

🇦🇹Austria mvonfrie

That is related to the HTML normalization "feature" of CKeditor 5. See https://github.com/ckeditor/ckeditor5/issues/16203 for more examples.

🇦🇹Austria mvonfrie

Using 2.0.1 on Drupal 10.2.5 and Drush 12.5.1.0, MR !11 breaks the functionality as described in #11 and #16.

I don't re-open because this already gets fixed by 🐛 There are no commands defined in the "ckeditor_media_embed" namespace. Needs review

🇦🇹Austria mvonfrie

Using 2.0.1, MR !14 works for me on Drupal 10.2.5 and Drush 12.5.1.0.

This partially reverts and therefore fixes Add Drush 12 compatibility for custom CKEditor Media Embed Plugin commands RTBC .

🇦🇹Austria mvonfrie

I just got the following warning after upgrading a site from 9.5 to 10.2:

Warning: file_get_contents(themes/custom/my_theme/../../../../../modules/contrib/colorbox/styles/default/colorbox_style.css): Failed to open stream: No such file or directory in Drupal\Core\Asset\CssCollectionOptimizerLazy->generateHash() (line 43 of core/lib/Drupal/Core/Asset/AssetGroupSetHashTrait.php).
Warning: file_get_contents(themes/custom/my_theme/../../../../../modules/contrib/colorbox/styles/default/colorbox_style.css): Failed to open stream: No such file or directory in Drupal\system\Controller\CssAssetController->generateHash() (line 43 of core/lib/Drupal/Core/Asset/AssetGroupSetHashTrait.php).

I can fix that by patching the colorbox.libraries.yml file like this:

plain:
  version: VERSION
  js:
    styles/plain/colorbox_style.js: {}
  css:
    theme:
-      styles/plain/colorbox_style.css: {}
+      styles/plain/colorbox_style.css: { preprocess: file }
  dependencies:
    - colorbox/init

But that doesn't really solve the issue here. The Drupal site is located at /var/www/html/ (web root is at /var/www/html/web/) which means that the ../../../../../

resolves to /var/www/modules/contrib/colorbox/styles/default/colorbox_style.css
instead of /var/www/html/web/modules/contrib/colorbox/styles/default/colorbox_style.css
and of course that file doesn't exist. I'm not sure whether this (the ../../ too much) is a bug in core or in the colorbox module. Therefore I didn't create an issue for that yet.

🇦🇹Austria mvonfrie

I get this error:

Fatal error: Declaration of Drupal\pluginformalter\DataCollector\FormAltersDataCollector::collect(Symfony\Component\HttpFoundation\Request $request, Symfony\Component\HttpFoundation\Response $response, ?Exception $exception = null) must be compatible with Drupal\webprofiler\DataCollector\FormsDataCollector::collect(Symfony\Component\HttpFoundation\Request $request, Symfony\Component\HttpFoundation\Response $response, ?Throwable $exception = null): void in /var/www/html/web/modules/contrib/pluginformalter/src/DataCollector/FormAltersDataCollector.php on line 55

This one is easy to fix, just the method signature changes from \Exception to \Throwable and the return type must be void.

I start a merge request for the changes, if there are more fixes needed they can be added there as well.

🇦🇹Austria mvonfrie

Publishing/unpublishing content has many effects including possible desctructive ones: assume someone has the unpublish * role but not the publish * role and clicks on the unpublish tab/local action by accident (or vice-versa). The user would not be able to revert this action on his own.

🇦🇹Austria mvonfrie

Just adding the dependency to composer.json and the info.yml is not enough because that will not install it. And depending on the site manager to install it manually is no good practice, as if they don't know and forget it, that will break the site. The safe option is to install it via an update hook.

🇦🇹Austria mvonfrie

Hello. I have a different use case but came across this issue when looking into the webform submissions delete form whether it would be possible to extend/path it for my use case. On a customers site the webform spam protection was not configured strong enough and now we have almost 40,000 submissions in a webform, of which 98 - 99 % are spam. With data analysis (# submissions per ip adress, email address etc.) and what is available I managed to marked most of the spam submissions as locked, with less than 500 remaining which the customer has to check manually.

So far so good. The next step is to clean the data tables from the spam submissions. My idea is to add an option to the clear (and purge) forms to only delete submissions which

  • * are locked (in my case the spam is locked)
  • * are not locked (in a case where it is easier to identify and lock the submissions to keep)
  • *ignore the locked state (current behavior)

As that could become a per webform or global purge setting as well and thus affect/extend the implementation of this issue, I first want to hear your opinion about it.

🇦🇹Austria mvonfrie

I'm looking for the same (merge a group specific menu into the main menu). But I would prefer a solution in Drupal Core which is independent from actually displaying the menu (aka it should work for decoupled menus as well).

🇦🇹Austria mvonfrie

Where is the change record regarding the removal of the $filters parameter of Group::getContentEntities($plugin_id, $filters) (or Group::getRelatedEntities($plugin_id, $filters) in 2.x/3.x)?

How can I rewrite my code which uses the filters? In my case the filter depends on the bundle type of the related entities, for type A I have to filter on the group owner UID, for type B on the current user UID. And there are two more filters to apply, which are more difficult to explain.

🇦🇹Austria mvonfrie

@mrweiner I get the following output from Drupal Upgrade Status. Except the core_version_requirement,/em> all reported issues are in tests only. I don't know why rector didn't fix them when you changed this issue back to active. But it would be really nice if you could apply them (eventually manually) and create a D10 compatible release soon. Maybe you can even publish a D10 compatible release without fixing the tests now (as their outcome should not be affected) and fix the tests later if you don't have so much time now? Thanks.

Cache Register 1.0.2
Scanned on Wed, 11/15/2023 - 17:35.

31 errors found. 1 warning found. Avoid some manual work by using drupal-rector
for fixing issues automatically or Upgrade Rector to generate patches.

web/modules/contrib/cache_register/tests/src/Kernel/CacheRegisterKernelTestBase.
php:
┌──────────┬──────┬─────────────────────────────────────────────────────┐
│  STATUS  │ LINE │                       MESSAGE                       │
├──────────┼──────┼─────────────────────────────────────────────────────┤
│ Fix with │ 194  │ Call to deprecated method assertNotEqual() of class │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertNotEquals() instead.                   │
│          │      │                                                     │
│ Fix with │ 203  │ Call to deprecated method assertNotEqual() of class │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertNotEquals() instead.                   │
│          │      │                                                     │
└──────────┴──────┴─────────────────────────────────────────────────────┘

web/modules/contrib/cache_register/tests/src/Kernel/DrawerTest.php:
┌──────────┬──────┬─────────────────────────────────────────────────────┐
│  STATUS  │ LINE │                       MESSAGE                       │
├──────────┼──────┼─────────────────────────────────────────────────────┤
│ Fix with │ 18   │ Call to deprecated method assert() of class         │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertTrue() instead.                        │
│          │      │                                                     │
│ Fix with │ 26   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
│ Fix with │ 29   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
│ Fix with │ 45   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
│ Fix with │ 81   │ Call to deprecated method assertNotEqual() of class │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertNotEquals() instead.                   │
│          │      │                                                     │
│ Fix with │ 82   │ Call to deprecated method assertNotEqual() of class │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertNotEquals() instead.                   │
│          │      │                                                     │
│ Fix with │ 83   │ Call to deprecated method assertNotEqual() of class │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertNotEquals() instead.                   │
│          │      │                                                     │
│ Fix with │ 87   │ Call to deprecated method assertNotEqual() of class │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertNotEquals() instead.                   │
│          │      │                                                     │
│ Fix with │ 90   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
│ Fix with │ 92   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
│ Fix with │ 93   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
└──────────┴──────┴─────────────────────────────────────────────────────┘

web/modules/contrib/cache_register/tests/src/Kernel/ManagerTest.php:
┌──────────┬──────┬─────────────────────────────────────────────────────┐
│  STATUS  │ LINE │                       MESSAGE                       │
├──────────┼──────┼─────────────────────────────────────────────────────┤
│ Fix with │ 25   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
│ Fix with │ 41   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
└──────────┴──────┴─────────────────────────────────────────────────────┘

web/modules/contrib/cache_register/tests/src/Kernel/RegisterTest.php:
┌──────────┬──────┬─────────────────────────────────────────────────────┐
│  STATUS  │ LINE │                       MESSAGE                       │
├──────────┼──────┼─────────────────────────────────────────────────────┤
│ Fix with │ 25   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
│ Fix with │ 34   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
└──────────┴──────┴─────────────────────────────────────────────────────┘

web/modules/contrib/cache_register/tests/src/Kernel/SlotBaseTest.php:
┌──────────┬──────┬─────────────────────────────────────────────────────┐
│  STATUS  │ LINE │                       MESSAGE                       │
├──────────┼──────┼─────────────────────────────────────────────────────┤
│ Fix with │ 32   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
│ Fix with │ 53   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
│ Fix with │ 119  │ Call to deprecated method assertNotEqual() of class │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertNotEquals() instead.                   │
│          │      │                                                     │
│ Fix with │ 125  │ Call to deprecated method assertNotEqual() of class │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertNotEquals() instead.                   │
│          │      │                                                     │
│ Fix with │ 145  │ Call to deprecated method assertNotEqual() of class │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertNotEquals() instead.                   │
│          │      │                                                     │
│ Fix with │ 160  │ Call to deprecated method assertNotEqual() of class │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertNotEquals() instead.                   │
│          │      │                                                     │
└──────────┴──────┴─────────────────────────────────────────────────────┘

web/modules/contrib/cache_register/tests/src/Kernel/SlotTest.php:
┌──────────┬──────┬─────────────────────────────────────────────────────┐
│  STATUS  │ LINE │                       MESSAGE                       │
├──────────┼──────┼─────────────────────────────────────────────────────┤
│ Fix with │ 27   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
│ Fix with │ 60   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
│ Fix with │ 64   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
│ Fix with │ 76   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
│ Fix with │ 78   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
│ Fix with │ 93   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
│ Fix with │ 95   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
│ Fix with │ 96   │ Call to deprecated method assertEqual() of class    │
│ rector   │      │ Drupal\KernelTests\KernelTestBase. Deprecated in    │
│          │      │ drupal:8.0.0 and is removed from drupal:10.0.0. Use │
│          │      │ $this->assertEquals() instead.                      │
│          │      │                                                     │
└──────────┴──────┴─────────────────────────────────────────────────────┘

web/modules/contrib/cache_register/cache_register.info.yml:
┌──────────┬──────┬────────────────────────────────────────────────────────────┐
│  STATUS  │ LINE │                          MESSAGE                           │
├──────────┼──────┼────────────────────────────────────────────────────────────┤
│ Check    │ 0    │ Value of core_version_requirement: ^8 || ^9 is not         │
│ manually │      │ compatible with the next major version of Drupal core. See │
│          │      │ https://drupal.org/node/3070687.                           │
│          │      │                                                            │
└──────────┴──────┴────────────────────────────────────────────────────────────┘
🇦🇹Austria mvonfrie

I really like to see this as well, no matter where it will be implemented. I currently have an issue with updating json_field from 1.0-RC4 to 1.0 or even 1.2, which is caused by the fix for #3252426 🐛 Support sqlite; set sqlite_type to native JSON field Fixed . This module cannot update the fields automatically because they have contents. In this case that should not matter because the change is about the SqlLite data type and I'm not using SqlLite.

🇦🇹Austria mvonfrie

About #39 the error message in commerce order there is already an issue ( Commerce #3336653 💬 Support setting theme for entity print patch Needs review ), added it as child issue.

🇦🇹Austria mvonfrie

Self-linking doesn't make sense, here is the correct link.

🇦🇹Austria mvonfrie

Linking the issue mentioned in the description for better tracking. The patch doesn't work with MR 16 from that issue.

🇦🇹Austria mvonfrie

mvonfrie made their first commit to this issue’s fork.

🇦🇹Austria mvonfrie

I just created a separate branch and MR 60which so far works, but we need to add the changes described in #38 there as well.

🇦🇹Austria mvonfrie

I have the same error message as in the description on my local instance and the following one on our test server (which configured exactly the same as the future production server except the hostname):

Warning: file_get_contents(): open_basedir retsriction in effect. File(/sites/default/files/css/css_OTs7jT_btKWU2MLco9kpWeRL-rV2o_TgZa4ICtteRCk.css?delta=0&language=de&theme=drowl_child&include=eJxLKcovz4lPzsjMSdFPzU3MzNEprsxNy8-rjAdxUov0S1KLSwAYzA7M) is not within the allowed path(s): (/var/www/vhosts/***Hostname removed***/:/tmp/:/var/lib/php/sessions) in Drupal\symfony_mailer\Plugin\EmailAdjuster\InlineCssEmailAdjuster->postRender() (line 78 of modules/contrib/symfony_mailer/src/Plugin/EmailAdjuster/InlineCssEmailAdjuster.php).

That error message ("open_basedir restriction in effect") might give a better understanding of what's causing the error than "Failed to open stream: No such file or directory": The path to the CSS file starts with a / so it is kind of rooted. If we check other usages of the standard Drupal function getCssAssets() we i.e. can find Drupal\Core\Render\HtmlResponseAttachmentsProcessor::processAssetLibraries() which passes the result of getCssAssets() directly to Drupal\Core\Asset\CssCollectionRenderer::render() to create HTML <link> render arrays for all assets. This means, in that (and all other cases I found) the path is web-rooted to be output as

<link rel="/sites/default/files/css/css_OTs7jT_btKWU2MLco9kpWeRL-rV2o_TgZa4ICtteRCk.css?delta=0&language=de&theme=drowl_child&include=eJxLKcovz4lPzsjMSdFPzU3MzNEprsxNy8-rjAdxUov0S1KLSwAYzA7M" />

but in our case the path is rooted against the linux file system. Therefore, I don't understand the very long discussion and complex ideas to solve this. In my opinion it is very easy to solve:

Proposed resolution

  • Prepend $file['data'] with Drupal's app.root path value. Considering the differences between >= 10.1 and < 10.1 we can do this conditionally only if stripos($filePath, '/') === 0 // Make sure to use type-safe comparison as we want to check against position 0 and not FALSE indicating that $haystack does not contain $needle!
  • Furthermore, we need to load the CSS file from the file system and not via HTTP(S) for inlining, so we need to get rid of the url params.

Starting example:

public function postRender(EmailInterface $email) {
    // Inline CSS. Request optimization so that the CssOptimizer performs
    // essential processing such as @import.
    $assets = (new AttachedAssets())->setLibraries($email->getLibraries());
    $css = '';
    $rootPath = \Drupal::getContainer()->getParameter('app.root');
    $logger = \Drupal::logger('symfony_mailer');
    foreach ($this->assetResolver->getCssAssets($assets, TRUE) as $file) {
      $filePath = $file['data'];

      // Only if we have a rooted path (which means it is web-rooted).
      if (stripos($filePath, '/') === 0) {
        // Correct the path to be linux-rooted.
        $filePath = $rootPath . $filePath;
        // Remove the query string which we don't need to load the file.
        if (($pos = stripos($filePath, '?')) !== FALSE) {
          $filePath = substr($filePath, 0, $pos);
        }
      }
      
      try {
        $logger->info('Loading CSS from file: %file.', ['$file' => $filePath, 'file' => $file]);
        $css .= file_get_contents($filePath);
      }
      catch (\Exception $e) {
        $logger->error('Failed to load CSS from file: %file. Error: %error', ['$file' => $filePath, 'file' => $file, '%error' => $e->getMessage(), 'error' => $e]);
      }
    }

    if ($css) {
      $email->setHtmlBody($this->cssInliner->convert($email->getHtmlBody(), $css));
    }
  }
🇦🇹Austria mvonfrie

Or write an post update hook which loops over all invoices and if they have a PDF generated, moves the file and updates the file entity accordingly.

🇦🇹Austria mvonfrie

Possibly the code running in the background to generate the invoice and send the email is using the wrong theme. Checkout Entiyty Print #2860122 Add option to set theme used for entity_print rendering Add option to set theme used for entity_print rendering Needs work

🇦🇹Austria mvonfrie

I have a very similar problem (please tell me if I should create a separate issue), using Drupal 10.1.2, Commerce 2.36.0, Commerce Invoice 2.0.0-RC3 and Entity Print 2.13.0.

My custom template in the site theme works perfectly fine when using the Entity Print route /print/pdf/commerce_invoice/1. But when I click on the module provided download link using its own route /invoice/1/download the PDF gets generated using the default template from the module instead of my custom template. Here it doesn't matter if I click the link from the admin view (admin theme) or the user view (custom theme).

🇦🇹Austria mvonfrie

I have the exact same problem, but with the paypal payment gateway as well and not only with the manual payment gateway. MR 6 fixes both cases for me and works well.

🇦🇹Austria mvonfrie

I just came across this issue when getting the error message "The @see reference should not contain any additional text" from PHPCS for an internal project.

I agree with #11 and understand all the pros and cons, though my failing use case of @see has not been discussed here and is somewhere in between. Like @Perignon I use @see for links when it is necessary for the understanding of some code. But unfortunately those specific links are very long and difficult to read, especially in rendered documentation like from PhpStorm.

Instead of

@see https://difficult-to-read-and-remember.hostname.com/1236456/some-very-long-and-crazy-url-which-nobody-will-understand-the-meaning-of-by-reading-this

I want to use

@see {@link https://difficult-to-read-and-remember.hostname.com/1236456/some-very-long-and-crazy-url-which-nobody-will-understand-the-meaning-of-by-reading-this Descriptive name of the linked page}

which then would be rendered as Descriptive name of the linked page (this link obviously doesn't work) linked to the given url.

🇦🇹Austria mvonfrie

@joachim, yes the 'bundle' bit should be removed too. But the field (plugin) id should be changed from 'computed' to 'field' as no computed plugin exists.

🇦🇹Austria mvonfrie

On Friday I tried MR !1864 but I was not able to apply that one as patch. For me it looks like that is an older MR which will be discarded in favor of !4224?

MR !4224 on 10.1.2 with Commerce 2.36.0 works for me for a computed bundle field on the commerce order item entity.

Nevertheless I found an error in the example in `views.api.php` in both MRs, as following the example in !4224 I got the error

The "computed" plugin does not exist. Valid plugin IDs for Drupal\views\Plugin\ViewsHandlerManager are: [list of found plugin ids]

See my review comment in !4224 for details.

🇦🇹Austria mvonfrie

Basically I agree with you that only stable versions should be used, but that's not always possible.

We had some problems which have been solved by 3367674 and as far as I remember from my colleagues other strange things as well, that's why we decided to switch to @dev until 2.10 gets released instead of applying the patch from that issue.

Then yesterday we suddenly started getting the described errors which are fixed by #bfdf0d3 and even if that commit is included in the beta1 I decided to directly go to the RC1 as RC should be more stable than beta.

🇦🇹Austria mvonfrie

Totally agree. I'm currently stuck in (3) always returning the $payment_method_type->createLabel() if there is only one option for a payment method type (in my case of paypal_checkout => "PayPal") and the customer requiring to customize the label (as his customers otherwise won't understand that they have to select that option to pay by credit card or EPS (Austrian online banking) which they can select on the next checkout step.

At the moment I don't have time to implement the event but will start with a small fix of changing the option label for (3) to use the payment gateway's display label. This way it gets customizable via configuration and if users don't have more than one gateway configured per payment method type this is an improvement already. Furthermore it will be in line with how the label is generated for (4).

🇦🇹Austria mvonfrie

Ok, just wanted to fix this and have seen that it already has been fixed in 4035fef ("Fixed for phpstan issues, etc.") by @gausarts which has no related issue.

But I will keep this open for now in case there are more PHP 8.2 compatibility issues.

🇦🇹Austria mvonfrie

For me MR 143 works.

🇦🇹Austria mvonfrie

@hatuhay please re-open this issue. The fix provided actually was wrong and worked only for a few weeks, as popperjs has been deprecated in Drupal 9.5 📌 Deprecate popperjs Fixed and removed from Drupal 10 in September 2022 .

Solution:

Include @popperjs/core directly in the theme and SASS subtheme starter kit via package.json and replace the dependency on core/popperjs by the local asset.

🇦🇹Austria mvonfrie

I have more or less the same issue with an indexed view for Commerce products, with Drupal 10.1 and all contrib modules up-to-date.

But in contrast to the others my problem is not the language of the contents (as they are theoretically in English and German, but currently there are no English translations of them). My problem is the interface language of the view. The site default language is EN (for technical reasons) and the content default language is German. This means the main language of the view is English and it is fully translated to German. But when I show it in German (/de/products) everything on the site is German except of the static view texts (title, global text area in the header, ...) is English. How do I get the view to display in the negotiated language correctly?

🇦🇹Austria mvonfrie

If the #3 warning should cause problems (it would block CI if you include phpstan in the automatic tests) this could be a workaround:

class MyService {

  protected static function getMessenger() {
    return \Drupal::messenger();
  }
}

I made the method protected to help with testing, this way it can be overridden to provide a mocked service instance easily.

59 Variable $messages might not be defined.

$messages is assigned inside a nested if statement inside the foreach loop, so the fix is very easy. Just add $messages = []; directly before the foreach loop.

🇦🇹Austria mvonfrie

Which warning exactly do you mean with #2? And #3 btw doesn't get triggered by static methods.

🇦🇹Austria mvonfrie

I didn't look on this issue for a while, but unfortunatley don't exactly know what it meant by

It is possible to programmatically emit a deprecation in older versions in the interest of consistency across multiple PHP versions.

PHPStan though is able to detect these issues, as I just got another one

Deprecated function: Creation of dynamic property Drupal\symfony_mailer\Processor\EmailBuilderManager::$proxy is deprecated in Drupal\symfony_mailer\Processor\EmailBuilderManager->getProxyMapping() (line 204 of modules/contrib/symfony_mailer/src/Processor/EmailBuilderManager.php).

which by PHPStan is reported as

 ------ ---------------------------------------------------------------------------------------------- 
  Line   src/Processor/EmailBuilderManager.php                                                         
 ------ ---------------------------------------------------------------------------------------------- 
  204    Access to an undefined property Drupal\symfony_mailer\Processor\EmailBuilderManager::$proxy.  
         💡 Learn more: https://phpstan.org/blog/solving-phpstan-access-to-undefined-property          
 ------ ---------------------------------------------------------------------------------------------- 

Find the full PHPStan report of the symfony_mailer 1.2.1 attached for reference (as it is too long to post it directly in the comment).

🇦🇹Austria mvonfrie

I have the exact same configuration (D10.0.9, DDEV 1.21.5) and for me this works out of the box. Can you check if the sendmail transport is set as default?

🇦🇹Austria mvonfrie

I installed commerce_stock as the dev version is D10 compatible now and looked a bit into the code to understand how things work and how to quirk a solution for my example into my site. As I have a deadline for the project I can't wait until this feature is implemented but have to find a custom solution in the meantime.

But I have an idea for a concept how to implement this properly. This can't be fully implemented in commerce_stock though as it would require changes in commerce/commerce_product which then are permanent and would make things even more complicated. So the concept will always require custom code by the site developer.

Currently all stock logic is connected to the PurchasableEntityInterface which basically (only) is the product variation entity (but can be extended by contrib modules to nodes for example). But of course we don't want (and don't need) to make the product entity purchasable in order to let it handle the stock of it's variations.

So we need two new interfaces plus traits providing their implementations for commerce products:


/**
 * Defines the interface for stockable entities.
 *
 * The entity type implementing this interface should always be implementing \Drupal\commerce\PurchasableEntityInterface
 * as well. An implementation for commerce product variations is provided by StockableProductVariationTrait.
 */
interface StockableEntityInterface extends \Drupal\Core\Entity\ContentEntityInterface {

  /*
   * Returns the entity handling the stock level for this entity.
   *
   *  @return StockedEntityInterface|null
   */
  public function getStockedEntity(): ?StockedEntityInterface;
}

/**
 * The entity type handling the stock level for a purchasable entity, for example the commerce product for its product variations.
 *
 * An implementation for commerce products is provided by StockedProductTrait.
 */
interface StockedEntityInterface extends \Drupal\Core\Entity\ContentEntityInterface {
  // Everything we need here for stock handling...
}

/**
 * Implementation of StockableEntityInterface for commerce products.
 */
trait StockableProductVariationTrait {

  /**
   * {@inheritdoc}
   */
  public function getStockedEntity(): ?StockedEntityInterface {
    $stocked_entity = $this->getProduct();
    return $stocked_entity instanceof StockedEntityInterface ? $stocked_entity : NULL;
  }
}

/**
 * Implementation of StockedEntityInterface for commerce products.
 */
trait StockedProductTrait {
  // Everything we need here for stock handling...
}

Then stock checking and stock processing has to check: The given entity or purchased entity of the given order item

  • implements PurchasableEntityInterface but not StockableEntityInterface --> use it for stock handling
  • implements both interfaces --> use StockableEntityInterface::getStockedEntity()
    • the return value implements StockedEntityInterface --> use that entity for stock handling
    • the return value is NULL --> fall back to the parent entity implementing PurchasableEntityInterface
  • implements StockableEntityInterface but not PurchasableEntityInterface
    • the return value implements StockedEntityInterface --> use that entity for stock handling
    • the return value is NULL --> don't handle stock for it.

Of course this requires changes to all sub-modules of commerce_stock and is quite complex. But the same time it is very flexible as it allows to decide whether the product variation or product should handle the stock (or maybe a totally different entity implementing StockedEntityInterface and being return by StockableEntityInterface::getStockedEntity()) on a per-bundle basis.

The site developer would just need to create custom product and product variation classes implementing the interfaces and registering them properly. This can be done using hooks or more easier with the Bundle Class Annotations module.


/**
 * Custom product variation implementation using delegating its stock handling.
 *
 * @Bundle(
 *      entity_type = "commerce_product_variation",
 *      bundle = "my_product_variation_bundle",
 *      label = @Translation("Stock delegating product variation"),
 * )
class StockableProductVariation extends \Drupal\commerce_product\Entity\ProductVariation implements \Drupal\commerce_stock\Entity\StockableEntityInterface {

  use \Drupal\commerce_stock\Entity\StockableProductVariationTrait;
}

/**
 * Custom product implementation handling stock for its variations.
 *
 * @Bundle(
 *      entity_type = "commerce_product",
 *      bundle = "my_product_bundle",
 *      label = @Translation("Stock handling product"),
 * )
class StockableProductVariation extends \Drupal\commerce_product\Entity\Product implements \Drupal\commerce_stock\Entity\StockedEntityInterface {

  use \Drupal\commerce_stock\Entity\StockedProductTrait;
}

It would even be possible to mix this for a product type, for example a book product type with three different variation types book, ebook (like ePub, PDF, ...) and amazon_kindle_book. book and ebook variations could handle their stock on product level by implementing StockableEntityInterface (i. e. using local stock) while amazon_kindle_book handles its stock on the variation by using a custom amazon kindle stock implementation.

🇦🇹Austria mvonfrie

This also effects Webprofiler #64 where the webprofiler toolbar reports data to the backend via POST /admin/reports/profiler/frontend/{profile}/navigation. The route only allows HTTP POST but as the admin path check of the "admin language from user preferences" language negotiator can't pass the HTTP method to the AccessAwareRouter it fails with the MethodNotAllowedException, which happens at least once per main request.

Patch #74 seems to fix this. I can't 100% confirm yet as I have another issue with webprofiler to solve first.

🇦🇹Austria mvonfrie

Please make this more generic and pass through all query parameters. While destination needs special handling, other query parameters could just be passed through. Or if that is too open maybe trigger an event to retrieve the query parameters to pass for a specific request.

In my use case I need a query parameter "owner" in order to set the owner of the new entity to a defined user passed via query parameter (and hiding the author selection UI) instead of the current user creating the new entity. The entity is a commerce product which should be owned by the "seller" user (which has an "add product" action on its profile, accessible to the seller user and all shop managers + admins) and not the "shop manager" or admin user creating the product. Without this issue being generic my only option would be to add separate local actions per product bundle.

Production build 0.71.5 2024