Account created on 7 March 2019, over 5 years ago
#

Recent comments

🇩🇰Denmark Steven Snedker

Thank you!

I can confirm it works with a short URL like https://vertikal.dk/sites/default/files/keys.mp4

On URLs longer than 245 chars it breaks. Because the name of the video is supposed to fit in 255 chars.

In the MediaRemoteVideoFormatter.php I changed

public static function deriveMediaDefaultNameFromUrl($url) {
    $pattern = static::getUrlRegexPattern();
    if (preg_match($pattern, $url)) {
      return t('Video from @url', [
        '@url' => $url,
      ]);
    }
    return parent::deriveMediaDefaultNameFromUrl($url);
  }

to

public static function deriveMediaDefaultNameFromUrl($url) {
    $pattern = static::getUrlRegexPattern();
    if (preg_match($pattern, $url)) {
      return t('Video from @url', [
        '@url' => substr($url, 0, 200),
      ]);
    }
    return parent::deriveMediaDefaultNameFromUrl($url);
  }

to make it work.

I also had to relax getUrlRegexPattern() in order to make videos like
http://mywonderfulNAS.myds.me:8764/share.cgi/Homevideo%20U-Matic/1061.mp...
almost work.

In the MediaRemoteVideoFormatter.php I changed

public static function getUrlRegexPattern() {
    return '/^https?.*?\.mp4/';
  }

to

public static function getUrlRegexPattern() {
    return '/^http?.*/';
  }

The player is still adamant that "No video with supported format and MIME type found" - but this is probably not related to this module or this formatter.

At least the player will get the correct url this way.

🇩🇰Denmark Steven Snedker

The current documentation is clearly inadequate. It has not been updated for four years.

I wish I could update it on https://git.drupalcode.org, but I'm not allowed to neither edit nor fork over there.

So here's an error ridden, but hopefully useful, stab at some better documentation:

1. The Flysystem module page links to
http://cgit.drupalcode.org/flysystem/plain/README.md?h=8.x-1.x
This page look pretty ugly in a browser. Link to
https://git.drupalcode.org/project/flysystem/-/blob/2.0.x/README.md?ref_...
or some such instead.

Better yet. Include most of the documentation (100+ lines?) on the module page. It's a great place for documentation! People will probably be more likely to install it, if they get the full picture up front.

2. "Reducing technical debt and risk of vendor lock-in." is slightly better than the current "Reducing technical debt and chance of vendor lock-in."

3. Requirements and Installation boilerplate should be removed. This is definitely not the first module a novice Drupal user will choose to install. Spend your time on the important details.

4. "Stream wrappers are configured in settings.php (usually found in /sites/default/settings.php or /web/sites/default/settings.php".
There are two settings.php in a typical D10 installation (the other one is at /core/lib/Drupal/Core/Site). And nearly 20 *settings.php files. We'd hate to confuse people.

5. Troubleshooting. Fine. But place it after the Configuration bit, where people need it.

6. Configuration. The example does not work.

This example will work

$schemes = [
  'local-example' => [ // The name of the stream wrapper.

    'driver' => 'local', // The plugin key.

    'config' => [
      'root' => '/../../', // Path to directory outside Drupal. Maybe /var/www/html/storage or ../ works better, who knows? 'sites/default/files/flysystem' would be a part of the public file system.
      'public' => TRUE, // In order for the public setting to work,
      // the path must be relative to the root
      // of the Drupal install.

      // Optional settings that apply to all adapters.

      'name' => 'local-example', // Optional. Defaults to something secret.
      'description' => 'An example of a local flyssystem file system',  // // Optional. Defaults to something secret.

      'cache' => TRUE, // Cache filesystem metadata. Not necessary for
      // the local driver.

      'replicate' => 'ftp-example', // 'replicate' writes to both filesystems, but
      // reads from this one. Functions as a backup.

      'serve_js' => TRUE, // Serve Javascript or CSS via this stream wrapper.
      'serve_css' => TRUE, // This is useful for adapters that function as
      // CDNs like the S3 adapter.
    ],
  ],

    'ftp-example' => [
      'driver' => 'ftp',
      'config' => [
        'host' => 'ftp.storaro.it', // or whatever the name of your ftp host is
        'username' => 'storaro', // use a better username
        'password' => 'cin3matograph3r', // use a better password

        // Optional config settings.
        'port' => 21,
        'root' => '/var/www/html/storage',
        'passive' => true,
        'ssl' => false,
        'timeout' => 90,
        'permPrivate' => 0700,
        'permPublic' => 0700,
        'transferMode' => FTP_BINARY,
      ],
    ],
];

// Don't forget this!
$settings['flysystem'] = $schemes;

6) Troubleshooting. Have a look at the status report (admin/reports/status) to see if it works.
And on the status page, you should never write "ftp returned an error". That's close to useless. What error did it return? Should the user have a closer look at the hostname, port, username or password?

7) How to use the module.
"Now whenever you add a NEW file field to a node type/entiity type, you can decide which file system to use. You cannot change the file system for existing fields, though. Only new fields get the benefit of the module.

🇩🇰Denmark Steven Snedker

I, too, made a small module to mitigate this error. Back Button Disable Module .
I won't upload it as a proper Drupal module. Drupal 7 is soon end of life and uploading modules to drupal.org is a time-consuming chore.

🇩🇰Denmark Steven Snedker

I, too, made a small module to mitigate this error. Back Button Disable Module .
I won't upload it as a proper Drupal module. Drupal 7 is soon end of life and uploading modules to drupal.org is a hideous and time-consuming chore.

🇩🇰Denmark Steven Snedker

Updated. Do keep me posted as to how it works in a real life situation.

🇩🇰Denmark Steven Snedker

Verdammt! I hope to have a new CKEditor 5 compatible version up sometime next week. In the meantime, you can try with CKEditor 4 and see if you miss a feature: I might be able to fix it.

I expect to spend a pleasant hour makeing the module work with CKEditor 5 and two savagely bitter hours getting the new and improved version placed correctly on Drupal.org.

🇩🇰Denmark Steven Snedker

On the module page here at drupal.org, I think you should change

Installation and Setup
See the README.md for detailed instructions.

to

Installation and Setup
IMPORTANT! You most likely need to fiddle with .htaccess and composer.json in order to make this module work. See the README.md for detailed instructions.

This more effectively warns people that this installation is not business as usual.

The README.md is fine now, by the way.

🇩🇰Denmark Steven Snedker

Joachim is absolutely correct regarding docblocks (#29). They are easier to read when only 80 chars wide. "Make your docblocks easier to read by aiming for a width of 80 chars" is a clearly a sensible recommendation.

But, using the exact same example, everyone is way happier with the 96 char line at
https://git.drupalcode.org/project/drupal/-/blob/11.x/core/lib/Drupal/Co...
than with some chopped up, harder to read, 80 char monstrosity. And also already allowed per "Control structure conditions may exceed 80 characters, if they are simple to read and understand". But you

The same goes for mherchels 130 char line in #9. Way better than any chopped up 80 or 120 char monstrosity.
Also already allowed per "Control structure conditions may exceed 80 characters, if they are simple to read and understand".

Let's be pragmatic thinkers and doers and extend "may exceed 80 characters, if they are simple to read and understand" to everything.

No hard or soft limits. Just (modern) common sense recommendations on legibility.

🇩🇰Denmark Steven Snedker

Removed an invalid example. A tag named 1.0.0-beta1 will show up as an option when you "Add new release".

🇩🇰Denmark Steven Snedker

@hansfn
I keenly followed the steps provided on the Version control tab for my module.

This ends with:

Creating releases

See the  naming conventions  for a complete description of how to name branches and tags so you can create releases.

Branch for a dev release

This creates and checks out a new branch in one command, then pushes it to Drupal.org

git checkout -b 1.0.x
git push -u origin 1.0.x

Tag for a stable release

git tag [tag name]
git push origin tag [tag name]

Once you’ve pushed the properly-formed tag or branch, see  Creating a project release  for directions to actually create the release node.

Unguided fool that I am, I chose a tag name that was not 1.0.1 or 1.1.0. And became none the wiser reading  Creating a project release  (that did not, at that point, link to Release naming conventions ).

I think I have now improved  Creating a project release  and  Release naming conventions  by making it clear what a tag should look like in order for the Add new release  bit to work.

I would love for the "Tag for a stable release" bit of the  Version control tab to sport a specific and useful recommendation. But I hope other beginners will find the nearby links to the newly improved  Creating a project release  and  Release naming conventions  useful when deciding on a (useful) name for the tag.

🇩🇰Denmark Steven Snedker

Linked to  the strict naming conventions  for branches and tags that you need to adhere to in order to make a release that you will actually be able to add and administer.

Made it clear that a tag should be three numbers separated by full stops (i.e. 1.0.0) in order for the release to be added and administered on the module page.

🇩🇰Denmark Steven Snedker

Explained the conventions on branch and tag naming in more detail in order to make it easier for beginners (like me) to branch and tag stable releases that'll actually show up on the module page at Drupal.org.

🇩🇰Denmark Steven Snedker

Disclaimer: I'm an impatient man of average intelligence. Thus, I need better documentation than most other module maintainers.

I would like this page, Creating a Project Release, to solve this problem:

I've managed to

On "Administer releases", https://www.drupal.org/node/2210155/edit/releases , I've filled out the checkboxes "Supported" and "Recommended".

But it does not show up as recommended at  https://www.drupal.org/project/wayback_filter

Also I'm unable to make another release at https://www.drupal.org/node/add/project-release/2210155 (reading Release naming conventions at  https://www.drupal.org/node/1015226 offered no useful solutions).

Second disclaimer:
"If you are looking for help with your Drupal site, please visit the support page".

I will.

But I think this very page Creating a Project Release should enable me, an impatient man of average intelligence, to do such a simple thing. I think this page (or some other nearby documentation page) should be improved to the point where I'm able to actually create a project release and have it show up correctly on the relevant pages.

🇩🇰Denmark Steven Snedker

I can't find a good source telling me that embedding external images in my site is a GDPR no-go. Do you have one?

But I can find several fresh sources telling me that embedding external fonts in my site is a no-go.

That's about the same.
So embedding external images in my site is probably a GDPR no-go.

I've augmented a local version the External Link Preview module with caching. However, if you're caching, you risk running into a speculative invoicing businesses. All over the world representatives of right holders will send you letters demanding 500 EUR per image you cache!

It happened to me in Denmark and your browser can probably translate most of I linked to a newspaper and received af 500 EUR invoice for you.

So. The External Link Preview module is
no caching: horribly slow, probably violating GDPR, safe from most speculative invoicing businesses
caching the external HTML locally: way faster, still violating GDPR, safe from most speculative invoicing businesses
caching the external HTML and images locally: way faster, GDPR compliant, exposed to speculative invoicing businesses

Sites like Facebook are caching 100% of the external images used for link previews. As they should. But they have a way bigger budget and way bigger legal department than the average user of the Drupal CMS.

I've thought about merging the caching version of the External Link Preview module into the more modern Link Field Preview .

But I do not want for anyone to break GDPR or open themselves to extortion from speculative invoicing businesses. So I have done exactly nothing for a couple of years (other than writing a few articles about the nasty, time wasting speculative invoicing businesses).

It's hard to see how we can fix GDRP compliance without exposing the users to huge financial risks.

🇩🇰Denmark Steven Snedker

I can expand a little on the troubles Potassiumchloride is experiencing.

Having Fullcalendar View display a (day) calendar based on a daterange field with multiple values works like a charm. Until you add filters.

Some filters work well
i.e node type == appointment, published== yes.
You get single entries in the calendar, and they're wonderfully draggable and editable.

Others filters carry penalties
date_range_field == not empty will result in those undraggable, duplicate entries we see in #2 💬 Duplicates of node with multiple date values Closed: outdated .

field_car_term == 3 will make entries based on nodes with a changed date different from today invisible. I have not finished investigating this strange error. Can only say it apparently does not matter if the Default date source of the view is Current date, Date of first view result or Fixed value.

Changing or adding view filters programmatically offers no escape. The troubles caused by filtering persists.

So the best advice for now is: Are you getting no or duplicate entries? Try removing the filters one by one until there are no errors.

🇩🇰Denmark Steven Snedker

When Drupal has very, very convoluted syntax and very little useful documentation, ChatGPT is usually awesome.

Asking Google or Drupal for "How do I add a tooltip (title) to the summary of a Drupal 9 details render array?" is a waste of time. Asking ChatGPT elicits a perfect answer in seconds.

ChatGPT does struggle though in places where the required Drupal syntax is very unintuitive. An example

$view->display_handler->options['filters']['field_car_term_target_id']['value'] = $term->tid;

will not in any way alter the filter of a view you have loaded in Drupal 9. You'll just get the predominantly useless error message Improve error messages, by including the source Active :

Argument #1 ($array) must be of type array, string given inarray_filter() (line 136 of core/modules/views/src/Plugin/views/filter/ManyToOne.php

I tried to coax a better answer out of ChatGPT. But the correct answers came from rote trial and error:

$view->display_handler->options['filters']['field_car_term_target_id']['value'][$term->tid] = $term->tid;
$view->display_handler->options['filters']['field_car_term_target_id']['value'][3] = $term->tid;
$view->display_handler->options['filters']['field_car_term_target_id']['value']['forsomereasonyoucanwritewhateveryouwant'] = $term->tid;

But usually ChatGPT is a very, very good ally against the many time sinks.

I highly recommend it.

🇩🇰Denmark Steven Snedker

This bug/sad state of affairs reminds of an old Drupal 7 bug:

format_date blows up with an unintelligible error message if it gets NULL or thinks the numbers it gets are strings.

Fixing this now been discussed for 10 years (!).

Bright and friendly people have made format_date more robust with a few lines of additional code .

Result?
They have been asked to:
A) to follow Drupal's syntax to the letter
B) not to actually make the format_date function more robust. Or spew a useful error, when fed, say, a NULL value.

After 10 years of discussion and great fixes, it's a "Won't fix!"

Oh well. Still I will try to be a charitable developer and at least try to make my own modules as robust as possible and provide useful error messages. I wouldn't like for Drupal to turn inscruteable and unforgiving everywhere.

🇩🇰Denmark Steven Snedker

This bewildering Drupal core bug is now reported as Invisible and wrong error message when flood controlled users ask for a password reset mail 🐛 Invisible and wrong error message when flood controlled users ask for a password reset mail Active .

🇩🇰Denmark Steven Snedker

The bug hunts in Drupal 4-7 were shorter. The simpler architecture meant that you could usually locate the bug in minutes instead of hours. You only had to spend minutes on trial&error, not hours.

Sadly neither I can see a path ahead toward better error reporting in (soon to be obsolete) Drupal 8 and 9.

We might collectively make Drupal 10 a little bit more robust by making our code more robust, using way more is_string(), !empty(), isset(), get_class() etc. But the error reporting will be stuck at suck, I'm afraid. It's way above my technical and social skills to affect useful change here.

🇩🇰Denmark Steven Snedker

I still haven't enjoyed a Drupal week with less than two hours of wild goose chases. So The Wayback Filter module has not yet been updated to D10.

I'm also waiting for a peeve to get resolved: the 2½ year old  Increase line length limit coding standards issue . Updating The Wayback Filter Module I also need to brace myself for some convoluted git and version workflows, I fear. Not today, Drupal.

But you are right. A tired and despondent tone is not at all helpful.

A few hours ago I helped a contrib developer, I think. I showed him how to spend more hours on the module in order for updates to break in fewer places 🐛 Updating from 1.0.2 to 1.04 breaks the site Active . I hope a few people will find it and find it useful. Using ChatGPT instead of Drupal.org to get useful documentation and working examples is generally also an idea worth promoting everywhere.

🇩🇰Denmark Steven Snedker

I see absolutely no reason for a 40, 80 or 120 characters hard limit.
If a visually impaired developer chooses to develop on a 14" laptop using a huge font-size, this fine human will just have to make his editor wrap the code.

Paqualle pointed to this response from Linus:

So the fact is, many of us have long long since skipped the whole "80-column terminal" model, for the same reason that we have many more lines than 25 lines visible at a time.

And honestly, I don't want to see patches that make the kernel reading experience worse for me and likely for the vast majority of people,
based on the argument that some odd people have small terminal windows.

If you or Christoph have 80 character lines, you'll get possibly ugly wrapped output. Tough. That's _your_ choice. Your hardware limitations
shouldn't be a pain for the rest of us.

Longer lines are fundamentally useful. My monitor is not only a lot wider than it is tall, my fonts are universally narrower than they are
tall. Long lines are natural.
[...]

So no. I do not care about somebody with a 80x25 terminal window getting line wrapping.

For exactly the same reason I find it completely irrelevant if somebody says that their kernel compile takes 10 hours because they are doing kernel development on a Raspberry PI with 4GB of RAM.

People with restrictive hardware shouldn't make it more inconvenient for people who have better resources. Yes, we'll accommodate things to within reasonable limits. But no, 80-column terminals in 2020 isn't "reasonable" any more as far as I'm concerned. People commonly used
132-column terminals even back in the 80's, for chrissake, don't try to make 80 columns some immovable standard.

If you choose to use a 80-column terminal, you can live with the line wrapping. It's just that simple.

So I'm +1 for no hard limits and +1 for no soft limits. PHPCS unable to do soft limits? Not our problem.

Just ditch the ancient character limits.

I'm sure this will lead to happier developers and more legible code for +97% of the developers.

🇩🇰Denmark Steven Snedker

I've set up xdebug to work with VS Code following these instructions (here's a video). I hope Sublime Text works more or less the same way.

Xdebug It shaves a few minutes off debugging as you do not have to print or log as many values. But it's not a silver bullet.

I'm afraid Jaypan's fine explanation is correct in most cases.

In this particular case:

Warning: Array to string conversion in Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::castValue() (line 2579 of core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php).

Drupal Core could probably try to var_dump Array in order to help the blameless Drupal webmasters. That might sometimes give someone a clue as to where the bug might be located. But sometimes the arrays are so huge, that trying to var_dump them will just give you a memory error on the server and/or kill your browser.

In this particular case var_dumping the array held no clue whatsoever as to where the bug was located.

And the verbose backtrace consisted of:

  • 32 Drupal\Core\
  • 3 Symfony\Component\HttpKernel
  • 2 Drupal\page_cache\
  • 1 Stack\StackedHttpKernel

All of them clearly correct, but not particularly helpful. Red herrings.

The core architecture of Drupal 8+ will have to change significantly for errors like these to be solveable in a reasonable amount of time by a reasonably experienced developer or webmaster.

🇩🇰Denmark Steven Snedker

Do you know if there's a correct way to remove submodules from your module?

ChatGPT has this suggestion which to me sounds right on:

If another user has not uninstalled one of your submodules and updates to the new version of your module that no longer includes that submodule, they will indeed get a fatal "submodule not found" error.

To prevent this error from occurring, you can add an update hook to your module that checks for the presence of the submodule and uninstalls it if it's found.

Here's an example of how you can do this:

Create a new file in your main module's directory called my_module.post_update.php.

In this file, create a function that checks if the submodule exists, and if it does, uninstalls it. Here's an example:

function my_module_remove_submodule() {
  $submodule_name = 'submodule_to_remove';
  if (\Drupal::moduleHandler()->moduleExists($submodule_name)) {
    \Drupal::service('module_installer')->uninstall([$submodule_name]);
  }
}

In this example, replace submodule_to_remove with the actual name of the submodule that you're removing.

In your main module's .info.yml file, add the following line:

post_update: my_module_remove_submodule

This tells Drupal to run the my_module_remove_submodule function when the module is updated.

Now, when a user updates to the new version of your module, Drupal will automatically check for the presence of the removed submodule and uninstall it if it's found, preventing the fatal "submodule not found" error.

God bless ChatGPT!

The core developers have been discussing how to make the module system less fickle for years and years 🐛 Moving modules breaks system Active .

But until they make the system more robust, I fear it's up to us to jump through these hoops in order not to break stuff.

Thank you for your work on the Threejs field 3d Object module.

🇩🇰Denmark Steven Snedker

I can see you asked nicely over at #3351526 Improve error messages, by including the source Active and someone dismissed it - or at least tried to - very fast. I hope someone working on that part of the system will at some point show up. Sadly my experience is that even bona fide bugs 🐛 Invisible and wrong error message when flood controlled users ask for a password reset mail Active elicit little interest. Often you'll just get an quick,  unhelpful message from a guy venturing that the problem actually isn't a problem.

But well. I'll try to keep my parts of Drupal working well, in the hope that the core devs will do the same. I promise to update Wayback Filter to D10 when I've enjoyed a Drupal week with less than two hours of wild goose chases.

You have encouraged me to "create an issue or two about [the bugs], in order to get them looked at and solved. This is Open Source after all, so we all need to chip in, to improve this great free software."

So today I have made this bug report  Updating from 1.0.2 to 1.04 breaks the site 🐛 Updating from 1.0.2 to 1.04 breaks the site Active . It looks like a small, local problem. But it really is part of a severe core problem.

🇩🇰Denmark Steven Snedker

Well @ressa, it's easy to get the useless error messages.

There are three steps to reproduce at the bug report 🐛 Fails on Drupal 9.5+ Fixed  and @clarksquared provided some nice screenshots of it 🐛 Fails on Drupal 9.5+ Fixed .

What should the title of your core issue be?

"Outlaw useless error messages and make Drupal more robust." or some variation, I think.

On my wish list, the stuff that's slowing down my work horribly, I find.

1. Useless error messages (the Field HTML example is a great example, even the best experts have no idea where the error is situated and have no way of finding out.... Other than time consuming trial and error)

2. Small errors that turn into fatal errors (the Field HTML example is a great example, a field does not provide a value (by design) - but suddenly you cannot save a node any more (one of Drupals most cherished features))

Expanding on this:

3. Errors messages should be easy to see for admins, but should also be easy to hide from average users.

4. Symphony errors should not brick the whole site.

And, straying even further from the focus, but I need to get this off my chest

5. Consistency and simplicity.
->title, ->getTitle() or ->get('title')?
->label, get('label') or ->field_label?
->label->value, label[0]->value, label[0]['value'], ['label']?
->value, ->target_id or ->email?
Making simple functions (like this one altering a node alias) often takes twice as much code as you'd expect.

6. You should be able to disable ALL caches and caching in one checkbox. Then you can add caching and refine as your site matures. Having to code just to avoid caching is the wrong way round.

7. Composer errors should be less useless.  If you accidentally run composer in the wrong directory (i.e. ROOT instead of ROOT/web these days) it'll offer up three wrong explanations as to why you cannot composer require 'drupal/readonly_html_field:^1.0'

I don't have any good experiences adding Drupal Core Issues.

My last one is  just sitting there 🐛 Invisible and wrong error message when flood controlled users ask for a password reset mail Active .

🇩🇰Denmark Steven Snedker

I, and every other user of the Readonly HTML Field module are grateful for your solution.

I've been writing Drupal modules (and a few field types) for 15 years. I'm stunned - on a daily basis - of just how much trial and error I have to go through to hunt down bugs (which I somehow feel arre getting more numerous across the board).

[Saving a node]
Warning: Array to string conversion in Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::castValue() (line 2579 of core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php).

did not offer me any clue whatsoever as to the origin of the, in real money, fatal error. At least in the old days of Drupal 4-7 you get a bit of a clue as to where a bug was situated.

Oh well. There's no magic tool or bullet. Just trial and error to deal with problems like this.

Once more: thank you for your help and your patch.

I proabaly should have used the Markup module .

🇩🇰Denmark Steven Snedker

Great solution!

But how did you get to it?

If I were as smart as you, how would I get from 

Warning: Array to string conversion in Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::castValue() (line 2579 of core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php)

to

Readonly HTML Field

to

implementing the isEmpty() method and always return TRUE

?

Yes, I want to become better at wrangling Drupal.

🇩🇰Denmark Steven Snedker

The Multiple fields remove button module does what we wish for. No need to update this module.

🇩🇰Denmark Steven Snedker

My tools were no match for this error message. Reading all 28 lines did not give me or my tools any clue as to what the problem was and where to actually find bug:

Warning: Array to string conversion in Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::castValue() (line 2579 of core/lib/Drupal/Core/Entity/Sql/SqlContentEntityStorageSchema.php).

Drupal\Core\Entity\Sql\SqlContentEntityStorageSchema::castValue(Array, Array) (Line: 1375)
Drupal\Core\Entity\Sql\SqlContentEntityStorage->saveToDedicatedTables(Object, , Array) (Line: 969)
Drupal\Core\Entity\Sql\SqlContentEntityStorage->doSaveFieldItems(Object) (Line: 721)
Drupal\Core\Entity\ContentEntityStorageBase->doSave(NULL, Object) (Line: 520)
Drupal\Core\Entity\EntityStorageBase->save(Object) (Line: 804)
Drupal\Core\Entity\Sql\SqlContentEntityStorage->save(Object) (Line: 339)
Drupal\Core\Entity\EntityBase->save() (Line: 270)
Drupal\node\NodeForm->save(Array, Object)
call_user_func_array(Array, Array) (Line: 114)
Drupal\Core\Form\FormSubmitter->executeSubmitHandlers(Array, Object) (Line: 52)
Drupal\Core\Form\FormSubmitter->doSubmitForm(Array, Object) (Line: 595)
Drupal\Core\Form\FormBuilder->processForm('node_testcontenttype_form', Array, Object) (Line: 323)
Drupal\Core\Form\FormBuilder->buildForm(Object, Object) (Line: 73)
Drupal\Core\Controller\FormController->getContentResult(Object, Object)
call_user_func_array(Array, Array) (Line: 123)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 580)
Drupal\Core\Render\Renderer->executeInRenderContext(Object, Object) (Line: 124)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array) (Line: 97)
Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}() (Line: 169)
Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object, 1) (Line: 81)
Symfony\Component\HttpKernel\HttpKernel->handle(Object, 1, 1) (Line: 58)
Drupal\Core\StackMiddleware\Session->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object, 1, 1) (Line: 48)
Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object, 1, 1) (Line: 51)
Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object, 1, 1) (Line: 23)
Stack\StackedHttpKernel->handle(Object, 1, 1) (Line: 718)
Drupal\Core\DrupalKernel->handle(Object) (Line: 19)
🇩🇰Denmark Steven Snedker

You are absolutely correct. I added a boolean field to an existing content type and pretty soon had

"NULL" in 5000 nodes
"0" in 200 nodes
"1" in 150 nodes

Loading all nodes without "1" took two fairly long entityqueries.

That sucks.

Thank you for pointing me to Field Defaults

That is the fastest, most robust and least sucky solution to this unfortunate problem.

Base property is a novel solution and creative. Well spotted. But knowing how Drupal is increasingly creaking under it's own weight I'll go with the simpler Field Defaults solution.

Thanks a lot for the answer.

🇩🇰Denmark Steven Snedker

Boolean field can have 2 states:
- NULL - the entity was never saved with the field, the field is empty
- 0/1 - the field has a value

A boolean with three values (NULL, 0, 1) has no upside whatsoever. At least I cannot imagine a single example where it's nice or convenient to use a boolean field to find out if a user has saved his/her user profile, webform or some node.

Booleans with three values (or two states and two values) makes a routine entityQuery awfully complex.

Here's an example:

$query = \Drupal::entityQuery('node')
  ->condition('type', 'measurement_result')
  ->condition('has_been_processed.value', 1, '!=')
  ->sort('changed', 'DESC')
  ->range(0, 20)
  ->accessCheck(FALSE)
  ->execute();

will not give me the 0 and NULL nodes. Only the has_been_processed=0 nodes.

So I have to make an additional

  $query = \Drupal::entityQuery('node')
  ->condition('type', 'measurement_result')
  ->notExists('has_been_processed.value')
  ->sort('changed', 'DESC')
  ->range(0, 20)
  ->accessCheck(FALSE)
  ->execute();

"Ah," you may say. "You can make that more compact. Try:

$orGroup = $query->orConditionGroup()
  ->condition('field_saved_as_single.value', 1, '!=')
  ->notExists('field_saved_as_single.value');

But no. That does not work. notExists's and isEmpty's are not welcome in orConditionGroup's.

Is there a simpler way to find out if a checkbox has been checked?
And if not, can we make it?

🇩🇰Denmark Steven Snedker

Well, SomebodySysop. I'm sorry that noone gave you a good answer in time and that the documentation for Drupal 9 is so awful. I try do document my own modules well, at least.

Anyway, here how I solved programmatically adding a filter to a view in Drupal 9.5. It may solve a problem for you in the future or bring some help to all the other lost developers looking for useful documentation and working examples.


I made a view (the format is Full Calender Display, but that doesn't matter) showing the jobs assigned to a specific car on a specific day.

My wish was to programmatically load and show a view block 10 times - once for each car on that day.

So in the views UI I added a filter for field_car_term set to 11.

Then I made this code:

function home() {
    $terms = \Drupal::entityTypeManager()->getStorage('taxonomy_term')->loadTree('cars'); // Get all terms from vocabulary
    foreach ($terms as $term) { // Loop through them
      $view = Views::getView('job_calendar');
      $view->setDisplay('block_1');

      unset($view->display_handler->options['filters']['field_car_term_target_id']['value']['11']); // Unset the hardcoded value
      $view->display_handler->options['filters']['field_car_term_target_id']['value'][$term->tid] = $term->tid; // Set the dynamic value

      $ret[$term->tid]['cal'] = $view->buildRenderable(); // Add the render array of the view to an array
    }

    return $ret;     // Return render array
}

The filter has to exist in the view. Otherwise the above code will not work.

The filter should be hardcoded to something that you later unset. Here it's term id 11.

Setting the filter, you have a surprising amount of freedom

$view->display_handler->options['filters']['field_car_term_target_id']['value'][$term->tid] = $term->tid;
$view->display_handler->options['filters']['field_car_term_target_id']['value'][3] = $term->tid;
$view->display_handler->options['filters']['field_car_term_target_id']['value']['drupalisawfullydocmented'] = $term->tid;

all work well.

The saner looking

$view->display_handler->options['filters']['field_car_term_target_id']['value'] = $term->tid;

does not work whatsoever. So avoid that.

I'd be thrilled if there was a better place to read about how to programatically add filters to a view. A place with more and better examples. But alas. Looking for hours I did not find such a place.

🇩🇰Denmark Steven Snedker

Patch #18 works: https://www.drupal.org/project/autologout/issues/3301642#comment-14764507 🐛 Throws Notice on Login when destination is set Needs work

🇩🇰Denmark Steven Snedker

Easily reproduced the error putting a destination on link to a form. Patch in #18 solved the problem. RTBC +1

Production build 0.69.0 2024