Victoria, BC
Account created on 26 June 2008, almost 17 years ago
#

Recent comments

🇨🇦Canada jaypan Victoria, BC

I don't know how to create a sub-theme

ressa linked to the method in his first reply.

🇨🇦Canada jaypan Victoria, BC

These changes will be wiped out next time you update your theme, which is why we recommended a sub theme.

🇨🇦Canada jaypan Victoria, BC

There's already a non-complicated way to do this using the REST API. Or, you can create a custom module with a route that would take parameters and create the node.

Yes, and you can also create custom Drush commands to run Drupal stuff from outside.

🇨🇦Canada jaypan Victoria, BC

jaypan created an issue.

🇨🇦Canada jaypan Victoria, BC

I have, and it works, but I don't myself like storing CSS in the DB, so I don't use it. I also don't recommend it for the same reason, though that's not to say I recommend not using it, rather that I just personally don't give recommendations for that module. It does work well.

🇨🇦Canada jaypan Victoria, BC

While the theme may have methods for adding your own CSS, if you use a sub-theme as ressa has suggested, it's easier to maintain over time. It's also easier to swap out the parent them in the future when you decide to go with a different theme.

🇨🇦Canada jaypan Victoria, BC

Yes, you can use Headless Drupal as the endpoints for creating apps. I have done it a number of times over the years.

Sites accessed through the browser make requests, that return data, markup (HTML), styling (CSS) and front-end functionality (JavaScript).

The same 'page' accessed through the app will only request raw data from the server. The markup, styling, and front-end functionality are all stored within the app when it is downloaded.

So when creating an app to work with Drupal, Drupal is used to create endpoints that the app requests data to.

🇨🇦Canada jaypan Victoria, BC

Nice. It seems like a beneficial command to me.

🇨🇦Canada jaypan Victoria, BC

Here's a tutorial that I wrote in a former life on using Drupal  with Composer. It's referring to Drupal 8, but it's still relevant for Drupal 10 and 11 for the most part.

🇨🇦Canada jaypan Victoria, BC

As of Drupal 10.3 (I think), modules and themes can only be managed using Composer.

🇨🇦Canada jaypan Victoria, BC

ressa has provided you with the Drupal way to do this.

Drupal has a flow of generating data, then passing it to the theming layer. Data is generated in core and modules. Theming is handled in themes. So the flow is essentially Core -> Module -> Theme. Adding templates would go against the Drupal paradigm, as it would be Core -> Module -> Theme -> Module. This can create difficult to debug errors.

Core and modules provide default templates for any theme hooks they define, so that theme developers have a base from which to custom. Core/module templates should only contain the required HTML to create a semantic document representing whatever the theme hook is displaying. And generally styling in the default templates provided by core/modules should be limited to layout/positioning of elements that will be consistent regardless of theme. Anything theme dependent is handled at the theme layer.

So if you want to override a template not belonging to your theme, you would, as ressa has stated, create a sub theme, and override the template there, rather than doing it in a module.

🇨🇦Canada jaypan Victoria, BC

Nothing stands out to me. If you remove the chunk of code I identified earlier, do you still get the error? I may have misdiagnosed.

🇨🇦Canada jaypan Victoria, BC

Here's a patch for 8.x-1.x for a stopgap, as the merge request is for the -dev branch.

🇨🇦Canada jaypan Victoria, BC

I wrote a tutorial a few years back on extending site configuration. Maybe this is what you want: https://www.jaypan.com/tutorial/drupal-extending-core-configuration-exte...

🇨🇦Canada jaypan Victoria, BC

I'm thinking your problem probably lies with this:

    foreach ($props as $prop => $value) {
      $element->set($prop, $value);
    }
    $element->save();

I'm thinking that it's sometimes passing a value that is not in the correct format. I would try to find a way to replicate the issue, then throw a debugger on the set() line, examining $prop and $value for each iteration to see if something stands out.

🇨🇦Canada jaypan Victoria, BC

Removing D7 example, as architecture has changed.

🇨🇦Canada jaypan Victoria, BC

This issue is still present in version 8.x.

🇨🇦Canada jaypan Victoria, BC

As even further forward thinking, there may even be a case for using the Subgroup module, and making Private Messages a Group type as well, then make them Subgroups of Private Message Threads.
For example, there could be a Group type of Private Message, and a Group type of Public Message. As each Group/message type would have it's own permissions by role, the public messages could be made visible to non members, with the private messages only visible to members. The thread itself could be made public, but the public would only be able to see the public messages, since they wouldn't have access to the private messages.

🇨🇦Canada jaypan Victoria, BC

Please note that I'm just putting this forward as a proposal - I don't have the bandwidth to implement it, nor do I remember the module architecture well enough, nor know the changes that have come about since, to be able to know the work required to bring about this architectural change. I'm just putting forth a proposal for the current maintainers to consider.

🇨🇦Canada jaypan Victoria, BC

I would create a page and drop the contact form block into the page with layout builder.

🇨🇦Canada jaypan Victoria, BC

Adding link to patch for maintenance-page--ofline template to work.

🇨🇦Canada jaypan Victoria, BC

DatabaseAccessDeniedException: SQLSTATE[HY000] [1045] Access denied for user 'root'@'localhost'

Looks like your DB credentials are incorrect in settings.php.

🇨🇦Canada jaypan Victoria, BC

Did you copy the webroot .htaccess to the server?

🇨🇦Canada jaypan Victoria, BC

Nice work.

🇨🇦Canada jaypan Victoria, BC

But the import then refuses that file. 

Error message?

🇨🇦Canada jaypan Victoria, BC

Views is rendered in the theme of the page that it is rendered on. If it an admin page, it will be rendered in the admin theme, if it's a front-end page, it will be rendered in the front-end theme.

Views pages are like any page in Drupal, that can have sidebars etc according to the them. Or, you can create a page with layout builder, and embed the view in that layout. Both options will allow for sidebars/layout.

🇨🇦Canada jaypan Victoria, BC

The updated interface on the field settings page is nice as well.

🇨🇦Canada jaypan Victoria, BC

Thanks, I was looking under the manage for tab. Much appreciated! Thanks again for the quick turn around.

🇨🇦Canada jaypan Victoria, BC

Thanks for the quick turnaround! I've just installed the latest version of the module, but I'm not seeing how to set individual form elements to not be rendered, Can you please provide some direction?

🇨🇦Canada jaypan Victoria, BC

I second DDev.

🇨🇦Canada jaypan Victoria, BC

I don't know this error you are facing. However, I don't see these libraries in your composer.json, so I woud:

  1. Make a copy of composer.json and composer.lock
  2. Use composer to require those modules (add them to composer.json)

See that resolves the issue.

🇨🇦Canada jaypan Victoria, BC

What does your composer.json look like?

🇨🇦Canada jaypan Victoria, BC

I don't think it was off topic. I was adding extra context as to what was happening with Solr in the background.

🇨🇦Canada jaypan Victoria, BC

This is very true, though technically Solr is not the database, as the Drupal DB is still the backend of the site. But data is duplicated on Solr for querying, and results queried from Solr are much, much faster, than DB queries.

🇨🇦Canada jaypan Victoria, BC

I've never seen anyone do a benchmark comparison with different compatible database types. But MySQL/MariaDB is the primary database used to power Drupal sites, and I've worked on massive corporate sites with tens of thousands of hits, using MySQL as the backend without issue.

🇨🇦Canada jaypan Victoria, BC

I personally avoid multisite, as it introduces a lot of complexity making it difficult to handle. It does have valid use cases, but what it won't do is allow you to share content between the sites. To do that you will need a different method. If you will have lots of content, then using the Domain module is an alternate that achieves similar goals as multisite but will allow sharing of content. If it was just one taxonomy I wanted to share however, I would create a view that dumps the terms from each site, and parsers on each site, with each site on a schedule to parse the dump and create any new terms from the site it's reading from.

🇨🇦Canada jaypan Victoria, BC

Sorry incorrect info

🇨🇦Canada jaypan Victoria, BC

You probably want internal:/api/27

🇨🇦Canada jaypan Victoria, BC

What is your goal from an end-user's perspective? And is there a reason why you are not defining your links in a .yml file?

🇨🇦Canada jaypan Victoria, BC

As someone who used to develop in MAMP, and switched to DDev, it's a very easy switch over, and any time spend trying to figure out MAMP ends up being time wasted. DDev just does it easier and better, and you'll actually be able to get more support since few Drupal developers develop directly in their local environment anymore, developers these days are using DDev or Lando or others. It's actually quite easy to set up, as it's installed with Homebrew, and it's quite easy to learn too.

🇨🇦Canada jaypan Victoria, BC

Have you looked into DDev? It's really easy to install on Mac with Homebrew, and it will solve all your issues as you won't use your native PHP/Mysql etc, everything is done in a Drupal-configured container that does not interfere with your system. I believe it's now the official local development environment for Drupal.

🇨🇦Canada jaypan Victoria, BC

The reason you are having difficulties, as that you are working against the Drupal design flow of: core -> module -> themes. Code is generated by core and modules, and handed off to the theme layer for theming.

When you put a template in a module, you are disrupting the flow -> core -> module -> theme -> module -> theme. This is why the template is not picked up in your module, because you are piping back up to the module layer from the theme layer.

Modules are meant to provide functionality, and themes provide markup. When functionality is specific to theme (aka - when the theme is changed in the future, the functionality does not need to persist), it can be created in the .theme file. When it's functionality that needs to be maintained if/when the theme changes in the future, the functionality would go in a .module file. In either way however, templates are meant to go in the theme. Modules must provide templates for any theme hooks the module declares, but this is so that a template exists until it is overridden in the theme layer.

🇨🇦Canada jaypan Victoria, BC

I do see the edit link. Just no link to create documentation. That said, I did a little Drupal hackery, examined the HTML to figure out what content type it is, guessed at the URL, and discovered that documentation pages, can be created (by me at least), at  https://www.drupal.org/node/add/documentation .

I created this page:  https://www.drupal.org/docs/develop/git/git-branching-strategy-for-multi...

Apparently only the guide maintainers can add it to the guide however. I set it as part of the GIt Version Control System guide, so hopefully they get a notification or something to review it.

🇨🇦Canada jaypan Victoria, BC

I'm thinking it may be a bit much for a single page. And no, I don't see any link on the link you gave to create a page, so I think I don't have permission.

🇨🇦Canada jaypan Victoria, BC

I can't figure out how to create a new documentation page. Do you know?

🇨🇦Canada jaypan Victoria, BC

When a developer tries to drush cim from the Git *.yml baseline folder, Drush will delete any configs from the developer's local Drupal site which are not included into the Git baseline folder. This implies if the developer has new configs for his local site (that he wants to keep), he should not drush cim from the Git baseline *.yml folder (doing so will wipe out his new configs that he has not pushed to Git yet).

With the flow I described above, a developer only ever does drush cim in a clean branch where all changes have been committed. So there will never be anything in their database they would want to keep, because they will already have committed their changes in their branch.

Now, you can imagine that sometimes mid-task, a developer may need to switch to another task, in which they may have changes they want to keep. Here is the full flow:

  1. Developer creates a new feature branch 1.x.x -> feature-1
  2. Developer makes some changes to config in the database
  3. Requirement comes in to immediately work on a different higher priority feature
  4. Developer exports their config drush cex - at this point, all changes the developer will have made, are reflected in code, between the exported config files and any changes module/theme files
  5. Developer stashes their change with git stash - Now the branch is back to the default state when it was created from 1.0.x. This can be confirmed with git status
  6. Developer checks out 1.x.x git checkout 1.x.x && git pull
  7. Developer creates a new feature branch git checkout -b feature-2
  8. Developer syncs their system with the codebase composer install && drush cr && drush updb && drush cim
  9. Developer makes their changes in feature-2
  10. Developer exports their changes, and commits them in feature-2 - now git is clean, with no unmerged files
  11. Developer is ready to go back to their original work. So they checkout their branch, and 'pop' the stashed code they stashed earlier git checkout feature-1 && git stash pop
  12. Developer has changed branches, so they sync their database with the code composer install && drush cr && drush updb && drush cim
  13. Now the developer can continue with their development of feature-1

As you can see, drush cim is only ever run in clean branches.

Therefore, a developer should always push his local config into Git first (so any new local configs are synced with Git). Now Git has his new configs *.yml, so he is now safe to drush cim from the Git baseline folder.

You have the correct idea here.

When a developer exports his Drupal site full archive and untar/unzip it into separate *.yml files, overlaying/copying his set of *.yml files with the Git baseline folder will not actually delete any *.yml files that is already in Git. Therefore, for the configs that the developer has deleted locally, the developer needs to visually identify and manually delete the *.yml from the Git baseline folder and commit/push the deletions to Git. There is really no other (easier/faster?) way of doing this. Is that correct?

There are no tarballs in the flow I described. Everything is managed through Git and Drush. If there is some situation where you would export a tarball of .yml config from a site and bring it into another installation, you would first delete ALL the config files in the destination instance, and then add the new configuration from the tarball. Config is a set package, and pulling it apart without a strong understanding of how the internal code relates to each other is likely to cause import problems.

Many of the *.yml has a UUID string. I read that when importing YAML configs, if Drupal sees a different UUID string, Drupal will delete the corresponding entity and re-create it. Since different developers with different local Drupal sites will have different UUID strings for the *.yml configs, wouldn't drush cim from the Git baseline cause entity/data loss from the developer's local Drupal site? Would this be a problem? Should I even worry about this or not so much? (I still am not clear on the implications of having different UUID strings in the *.yml files).

With the flow I described above, you do not have to worry about UUID, the system will accept them. In the case that you are bringing over a specific config .yml file from another installation and want to import it, you can delete the UUID from the file and Drupal will allow it to be imported (if everything else in the file is compatible with your system).

🇨🇦Canada jaypan Victoria, BC

Sure, I'm good with that :)

🇨🇦Canada jaypan Victoria, BC

This is how I handle this. First an explanation of my Git flow, how I address a few situations, then I'll answer your questions using my explanation as the context/reference.

My git flow:

  1. I always have a git branch that is a  mirror of production, in the format [MAJOR].x.x, eg 1.x.x. Development is not done on this branch. It should only ever be updated after a successful deployment to production, to ensure that it is an exact copy of production.
  2. I clone that branch, to an active development branch, in the format [MAJOR].[MINOR].x, eg git checkout 1.x.x && git pull && git checkout -b 1.0.x.
  3. When a developer starts work on code, they clone a new branch from the active development branch created in step 2. As 1.x.x is the same as the code on production, this ensures that the starting point for the code changes will work on production. For example 1.x.x -> feature-1. (Side note - I prefer to use ticket numbers for the branch name, so that everything is cross-referenceable, and means that any code changes will have an accompanying ticket from which to get information about the change)
  4. The developer synchronizes their local environment with the git branch:composer install && drush cr && drush updb && drush cim
  5. When the developer is finished their work, they export config to the file system, and comit the config .yml files.  they open a pull/merge request, to merge the feature branch into the active development branch, eg feature-1 -> 1.1.x.
  6. When a new release is to be deployed, a new Git tag is created in the feature branch, with the full version. Eg. 1.0.0, then 1.0.1, 1.0.2... and so on
  7. The this tag is checked out into testing environments, so that whomever is testing that the code works, can review it.
  8. If the testing fails, fixes are made in the feature branch relevant to the bug, eg feature-1, then go back to step 4. Repeat as necessary.
  9. When testing passes, the git tag is checked out in the production environment, containing all the tested code
  10. As the code on production and the main 1.x.x branch have now diverged, the release tag is merged into1.x.x, eg 1.0.8 -> 1.x.x. This once again makes 1.x.x an exact copy of the code checked out on production.
  11. Go back to step 2, and create a the next active development branch, ie 1.x.x -> 1.1.x. New PRs will now be committed to 1.1.x
  12. If any hotfixes are needed, the flow is 1.x.x -> Hotfix branch -> [next tag] -> 1.x.x -> 1.1.x. Or, in other words, a copy is made from the current production code into a hotfix branch, the fix is applied, the branch is merged back into the previous active development branch, and a new tag is generated. This tag can go through testing and to production. When it is deployed to production, it is merged back into the production mirror branch, and then into the current active development branch.

Note 1: In regards to step 3, branches will almost always be created from the production mirror. However, sometimes during active development, branches will require code that has been developed in another branch in active development. In this scenario, instead of creating the branch as described in step 3 above, it would be created from the feature branch it depends on, iefeature-1 -> feature-2

Note 2:  New major branches are created for major breaking code changes. For example when going from Drupal 10 -> Drupal 11, Git can be branched 1.x.x -> 2.x.x, an active development branch is created 2.x.x -> 2.0.x, and the Drupal upgrade to D11 would be handled as 2.x.x -> [UPGRADE BRANCH] -> 2.0.x. Regular non-D10 development would be handled in 1.x.x, to be merged into 2.x.x when ready.

Note 3: The advantage of an active development branch (step 2) can be seen with the following scenario:

  1. Three feature branches are created, feature-1, feature-2, and feature-3
  2. These branches are merged into the active development branch: 1.3.x
  3. Upon review, the client decides that they do not want feature-3 anymore. 

This creates an issue in that it is tricky to extract a feature branch after it has been merged, and in relevance to this particular thread, can cause issues with configuration. Due to the presence of an active development branch, the above issue can be resolved as follows:

  1. Create the next active development branch from the copy of the production code. In the above case that means1.x.x -> 1.4.x.
  2. Merge the branches that ARE to be deployed into the new development branch. For the example above, that means merging feature-1 and feature-2 into 1.4.x.
  3. 1.3.x is then abandoned.

That covers the logic behind how git branches are structured. It allows for flexibility as well as graduated releases based on a semantic versioning system.

In regards to your questions on configuration, let's dig deeper into steps 3-5 of the overall flow, on how an individual developer will deal with issues.

  1. Developer creates a new feature branch, eg 1.x.x -> feature-1
  2. Developer commits their changes, pushes their branch, and opens a pull/merge request
  3. Someone else has already made a commit that has conflicts. The pull/merge request will report this and not allow merging
  4. The developer, locally, checks out the the active development branch, which is conflicting, and pulls any new changes. They then merge the active development branch into their feature branch. If the active development branch is 1.0.x, that would be: git checkout 1.0.x && git pull && git checkout feature-1 && git merge 1.0.x
  5. Any conflicts require visual review and resolution of the conflict, sometimes in consultation with other developers to understand what is happening in the conflict
  6. Next, Drupal is synced with any code changes that have come into the branch from feature-1: composer install && drush cr && drush updb && drush cim
  7. The functionality of the branch is confirmed through the UI or whatever means, to ensure that merging in the changes from the active development branch did not break the new code. If anything needs fixing, it can now be fixed.
  8. Config is exported.
  9. The updated code is committed, and pushed
  10. The original pull/merge request blocked in step 3, is now not blocked and can be completed (unless someone in the meantime has pushed new conflicts)

Now, to address your questions, in regards to the above context of how I structure things:

Configs/YAML files that have been created by other developers representing new features from other developers (pulled from Git)

Any time developers changes branches, they must synchronize their DB with the code in the branch. This is seen in step 4 of the overall flow above, and in step 4 of the process of handling conflicts when running composer install && drush cr && drush updb && drush cim. The last step, drush cim, will import any changes in config that have come from other users, adding any new configuration.

Configs/YAML files that have been deleted/removed by other developers (pulled from Git)

Same as the above, any configuration removed by other users will be removed when the configuration is imported with drush cim.  

Configs/YAML files that have been a developer have added locally (representing new features on the site) (should be pushed to Git)

These are handled with the pull/merge requests. After the developer's code has been committed, and other users pull it to their system, they will import the changes into their local configuration with drush cim

Configs/YAML files that have been a developer have deleted locally (features removed from site) (should be pushed to Git)

Same as the last question, when a PR is merged, any removed config will then be removed from other environments as the code changes are merged, and the configuration is imported with drush cim

Configs/YAML files that have been modified both by the developer locally as well as modified by other developers (pull from Git)

These will result in merge conflicts, which are handled by the process I outlined above for handling conflicts. These can be messy to figure out, so it's best, when possible to not have developers working within the same area creating a situation in which they could be concurrently working on the same configuration. It's sometimes not possible to avoid however, in which case, discussion between the developers when resolving merge conflicts is essential, to ensure everyone's required code is present.

🇨🇦Canada jaypan Victoria, BC

Reported as spam.

🇨🇦Canada jaypan Victoria, BC

Love it :)

🇨🇦Canada jaypan Victoria, BC

That was your method of achieving some goal, not your goal.

No, I don't. But I know Drupal so-so, and thought maybe I could provide an alternate solution. But I don't have anything for you with your current method, best of luck.

🇨🇦Canada jaypan Victoria, BC

What is your goal behind this? There may be some other Drupal solution that does not use your method.

🇨🇦Canada jaypan Victoria, BC

A meaningless AI answer if I ever saw one.

🇨🇦Canada jaypan Victoria, BC

I just ran into this exact issue today, and I was not able to find a way to add/extend configuration to a views block. In the end, I went an alternate route - I created a block plugin, that has custom configuration, and renders the view.

Use case:

  1. I have a views block displaying items
  2. This block will be rendered in multiple areas on the site
  3. The header text for the block must be customizable in each area it is rendered in on the site
  4. For a clean UX, the header text must be entered when placing the block, ie in layout builder or on the block layout page (or anywhere else).

Solution:

<?php

declare(strict_types=1);

namespace Drupal\herons_base\Plugin\Block;

use Drupal\Core\Block\Attribute\Block;
use Drupal\Core\Block\BlockBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\StringTranslation\TranslatableMarkup;

/**
 * Creates a 
 */
#[Block(
  id: "abc_list_block",
  admin_label: new TranslatableMarkup("A listing of ABC block items"),
)]
class RepairJobCancelBlock extends BlockBase {

  /**
   * {@inheritdoc}
   */  
  public function defaultConfiguration() {
    return [
      'header_text' => [
        'value' => NULL,
        'format' => NULL,
      ],
    ];
  }
  
  /**
   * {@inheritdoc}
   */
  public function blockForm($form, FormStateInterface $form_state) {
    $header_text = this->configuration['header_text'];
    $form['header_text'] = [
      '#type' => 'text_format',
      '#title' => $this->t('Header Text'),
      '#default_value' => $header_text['value'],
      '#format' => $header_text['format'],
    ];

    return $form;
  }

  /**
   * {@inheritdoc}
   */
  public function blockSubmit($form, FormStateInterface $form_state) {
    $this->configuration['hello_block_name'] = $form_state->getValue('header_text');
  }


  /**
   * {@inheritdoc}
   */
  public function build() {
    $header_text = this->configuration['header_text'];

    return [
      '#prefix' => '<div class="abc_list_wrapper">',
      '#suffix' => '</div>',
      'header' [
        '#prefix' => '<div class="header-text">',
        '#suffix' => '</div>',
        '#type' => 'processed_text',
        '#text' => $header_text['value'],
        '#format' => $header_text['format'],
      ],
      'view' => [
        '#type' => 'view',
        '#name' => 'abc_blocks',
        '#display_id' => 'listing_block',
      ],
    ];
  }

}
🇨🇦Canada jaypan Victoria, BC

I've never seen a file extension with a hyphen. A google does not show me any links that say that hyphens are not allowed, but neither can I find any examples of file extensions that contain characters with anything other than numbers and letters. It seems Drupal will only allow letters, numbers and underscores. Is this file extension one you have created, or is it for some existing software?

🇨🇦Canada jaypan Victoria, BC

What is the error? This could maybe be a server configuration issue. Is the error coming from Drupal or the server?

🇨🇦Canada jaypan Victoria, BC

Export the content, find or build a sharepoint importer, import the content to Sharepoint.

But you won't find much more info than that here, as people would know how to import data from Sharepoint, not too. You're better off finding a Sharepoint forum to find out how to migrate data into sharepoint.

🇨🇦Canada jaypan Victoria, BC

You can open a ticket in the Drupal issue queue as a support request, requesting these be removed: https://www.drupal.org/project/issues/search/drupal

🇨🇦Canada jaypan Victoria, BC

You need to create the config directory as a sibling directory to your webroot.

So if your webroot is /path/to/webroot, it would be /path/to/config

🇨🇦Canada jaypan Victoria, BC

This is what view modes on entities are for. Each view mode allows for a different way to view the entity. You can choose which fields to show, and how they will display, and have different templates for each view mode.

🇨🇦Canada jaypan Victoria, BC

Due to the lack of detail, it's not at all clear what you are trying to do, that said, I doubt it's possible.

🇨🇦Canada jaypan Victoria, BC

At the time of writing, Drupal 11.2 has not been released and does not exist. The current version is 11.1.2. Did you manually change your composer.json file?

🇨🇦Canada jaypan Victoria, BC

Thank you!

🇨🇦Canada jaypan Victoria, BC

What does the PEVB module do wombatbuddy? I'm reading the module page, but can't fully understand what it does.

🇨🇦Canada jaypan Victoria, BC

In the end I went with a non-views solution. I think this may be a problem with Drupal core views, rather than this module specifically. I wasn't able to find a solution.

🇨🇦Canada jaypan Victoria, BC

I have recently for the first time used the Custom Field module , to accomplish the goal of what I used to do with Paragraphs module .

🇨🇦Canada jaypan Victoria, BC

I second the recommendation of the Groups module.

🇨🇦Canada jaypan Victoria, BC

The configuration API is how configuration like roles are moved between environments. Here's a comprehensive write up I did about it for Drupal 8, but it's still 95% the same: https://www.morpht.com/blog/drupal-8-configuration-part-1-configuration-api

🇨🇦Canada jaypan Victoria, BC

What is your system? Are you using DDev or any type of containerization/virtualization? Or are you running raw in your OS?

Usually this kind of discrepancy is because different tools are using different PHP instances. So your web server may be on php 7, while your command line is on php 8, or vice versa. And/or maybe Composer is configured to use a different PHP instance. The first thing to track down is where is Composer getting PHP 7 from? You must have it installed somewhere on your system so you'll need to track that down and work from there.

🇨🇦Canada jaypan Victoria, BC

Indeed :)

🇨🇦Canada jaypan Victoria, BC

Possible related core issue: https://www.drupal.org/project/drupal/issues/3097568 🐛 EntityViewsData does not generate a "additional fields" nor "delta" field for multivalue base fields Needs work

🇨🇦Canada jaypan Victoria, BC

Thanks for the quick response!

Doing some more investigation, this may not be a Search API specific issue, I have created a view working with the group entities directly rather than a search API index of the group entities, and I am finding the same behavior.

I will see if I can figure out something in the implementation of hook_views_data - maybe there is a way to add the delta to connect values.

🇨🇦Canada jaypan Victoria, BC

I agree with removing the dependency on ckeditor. I have downloaded this patch and tested it locally and it works.

🇨🇦Canada jaypan Victoria, BC

How are you saving the entity to the form state?

This can be done in formBuild() as the first thing before anything else:

// Attempt to retrieve the user entity from the form state.
if (!$user = $form_state->get('user_object')) {
  $roles = [
    'site_admin',
  ];

  // Create a new user.
  $user = User::create([
    'status' => 1,
  ]);

  foreach ($roles as $role) {
    $user->addRole($role);
  }

  // Store the user.
  $form_state->set('user_object', $user);
}

you can then retrieve it at any time, whether later in the formBuild step, and/or in validation, submission and ajax handlers, with $form_state->get('user_object').

If I had a field for the username, for example. I would do this:

$user = $form_state->get('user_object');
$form['username'] = [
  '#type' => 'textfield',
  '#title' => $this->t('Username'),
  '#required' => TRUE,
  '#default_value' => $user->getUsername(),
];

And in the submit handler for that step, I would do this:

$user = $form_state->get('user_object');
$user->setUsername($form_state->geValue('username'));
🇨🇦Canada jaypan Victoria, BC

I don't have a solution to your issue, but I can tell you how I deal with multistep forms. Generally a multistep form will be creating one or more entities. Imagine a site with comments enabled on posts. An anonymous user may click 'add comment', and be brought to a form that allows them to create a comment, and an account to be set as the author for the comment. An example form would have two steps, the first collecting the comment, and the second step collecting the account details. Upon completion of the form, the account is created and set as the comment author.

On the initial form build, I create an entity for a user, and an entity for a comment, with any default values. I do not call ::save() on them however. They are just two unsaved entities. These are then stored in the form state, for retrieval anywhere the form state is available on any step, validation handler, and/or submit handler.

Then, for each step of the form, I populate the form fields I'm creating from the values stored on the entity. For the initial load of each step, these values will be empty, so there will be no default value. In the submit handler for each step, the relevant entity is retrieved from the form state, any previously stored values for the relevant field are cleared, and the newly submitted values in the current step are stored.

So for the example form, upon submission of the first step of the form, the comment entity would be retrieved from the form state, the comment body field on the comment entity would be cleared, and the submitted value from the first step of the form would be set on the comment entity. The second step of the form would work the same way, retrieving the account entity, and setting submitted info on the account object.

Now imagine the user clicks the back button from the account information step, to go back to the comment step. When the comment step is rebuild, the comment entity is retrieved from the form state, and the value of the comment body field is set as the default value to the form element, and on submission, the existing value is cleared, with the new value stored.

All steps of the form work the same way - form elements are populated with entity field values, which are empty on initial load of the step, but may have a value on future loads of that step when using the back button. And finally, on form save at the final step, after adding the submitted values of the account step on the account object, the account object is saved, the new account ID is set as the author of the comment, and the comment is also saved.

🇨🇦Canada jaypan Victoria, BC

Glad to hear your got it worked out.

🇨🇦Canada jaypan Victoria, BC

In the format section, choose 'Unformatted list' (there are others you can select as well to show rendered entities, but a table for example does not allow for rendered entities)

Then for 'Show', select 'Rendered entity', and finally you will be given the option to choose the view mode.

🇨🇦Canada jaypan Victoria, BC

For the view mode, you would set only the image field to show. It sounds like there is a formatter to show the URI, but not the filename. In that case, I'd look to try to find a contributed module that provides a field formatter to show image filenames. If not, then this is where custom code would come into play - you would create a custom field formatter for image fields, and have it display the filename for the image: https://www.drupal.org/docs/creating-custom-modules/creating-custom-fiel...

Then everything else would be done the same as I stated - set the view to display entities, and use the view mode that only shows the image field, and the image field on that view mode will use the formatter you created above that displays the filename of the image.

🇨🇦Canada jaypan Victoria, BC

The template being used is core/themes/olivero/templates/content/node--teaser.html.twig.

You would copy this file to your theme directory's templates folder, and edit it. I can see that the date is indeed hard coded above the title in that template, so you would move it below the title. Make sure you copy the file to your theme, and don't edit the file itself, as that will get overwritten on your next core update. If you copy the file to your theme directory's templates folder, as long as it's a custom theme, it will not be overwritten.

🇨🇦Canada jaypan Victoria, BC

If you enable theme debug , what does it tell you for the output for this given template? Which template is it using, what are the override suggestions?

🇨🇦Canada jaypan Victoria, BC

I would probably not use this module as-is. It never got past an alpha version for D9, and dev for D10, which says it's probably very buggy. It's the type of module that if one wants to use it, they should be ready to do a lot of bug testing and fixing, and contributing code back to the module to get it working.

🇨🇦Canada jaypan Victoria, BC

Yes, you run them locally (your computer) and deploy the complete package to the server.

https://www.morpht.com/blog/drupal-and-composer-part-2-managing-drupal-8...

🇨🇦Canada jaypan Victoria, BC

The submit handler is probably tied to a specific button then, and not to the form as a whole. This means you'll have to set the function to be a #submit handler on your ajax button.

🇨🇦Canada jaypan Victoria, BC

Due to the HTML tag, I would use FormattableMarkup rather than Markup, though I haven't tested to see if it filters the style.

Production build 0.71.5 2024