Merge Requests

Recent comments

🇺🇸United States brooke_heaton

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

🇺🇸United States brooke_heaton

Ok, I pushed up a new approach that should vastly improve the speed and efficiency of this. I'm doing a leftJoin between login_history and the user table for any NULL values in the user table then I am able to fetch the array keys into one array and run a delete query with the set of deleted user IDs.


/**
 * Deletes records of deleted user from login_history.
 */
function login_history_update_8004() {
  $connection = Database::getConnection();
  $query = $connection->select('login_history', 'lh');
  $query->condition('lh.uid', 0, '<>')->addField('lh', 'uid');
  $query->leftJoin('users', 'u', 'lh.uid = u.uid');
  $query->isNull('u.uid');
  $results = $query->distinct()->execute()->fetchAllAssoc('uid');
  $results = array_keys($results);
  $count = count($results);
  if ($results) {
    $message = "Removing $count deleted user id from login_history table.";
    \Drupal::logger('login_history')->notice($message);
    $query = $connection->delete('login_history')
      ->condition('uid', $results, 'IN')
      ->execute();
  }
  $message = "Removal complete.";
  \Drupal::logger('login_history')->notice($message);
}

Feedback welcome on the PR.

🇺🇸United States brooke_heaton

A lot of developers miss the required fields method on a select query and it's not clearly outlined here that fields are REQUIRED by a dynamic select query or the query will fail. 

🇺🇸United States brooke_heaton

Sure, I can revise this to make this a left join instead. Let me see if I can rig that up. Might take a bit.

🇺🇸United States brooke_heaton

Added update hook to remove data on deleted users form login_history.

🇺🇸United States brooke_heaton

This ticket could likely also use an update hook to purge the data on any previusly deleted user accounts.

🇺🇸United States brooke_heaton

Oh interesting. Thanks for pointing that out. I'll look into it. Thanks Aaron!

🇺🇸United States brooke_heaton

Here is a full stack trace of my error, if this can help elucidate the problem. Sorry for any confusion:

Backtrace	
#0 /code/web/core/lib/Drupal/Core/Entity/Query/Sql/Query.php(80): Drupal\Core\Entity\Query\Sql\Query->prepare()
#1 /code/web/modules/contrib/salesforce/modules/salesforce_mapping/src/Plugin/Validation/Constraint/UniqueFieldsConstraintValidator.php(37): Drupal\Core\Entity\Query\Sql\Query->execute()
#2 /code/web/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php(202): Drupal\salesforce_mapping\Plugin\Validation\Constraint\UniqueFieldsConstraintValidator->validate(Object(Drupal\salesforce_mapping\Entity\MappedObject), Object(Drupal\salesforce_mapping\Plugin\Validation\Constraint\MappingSfidConstraint))
#3 /code/web/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php(154): Drupal\Core\TypedData\Validation\RecursiveContextualValidator->validateConstraints(Object(Drupal\salesforce_mapping\Entity\MappedObject), '000000000000212...', Array)
#4 /code/web/core/lib/Drupal/Core/TypedData/Validation/RecursiveContextualValidator.php(106): Drupal\Core\TypedData\Validation\RecursiveContextualValidator->validateNode(Object(Drupal\Core\Entity\Plugin\DataType\EntityAdapter), Array, true)
#5 /code/web/core/lib/Drupal/Core/TypedData/Validation/RecursiveValidator.php(93): Drupal\Core\TypedData\Validation\RecursiveContextualValidator->validate(Object(Drupal\Core\Entity\Plugin\DataType\EntityAdapter), NULL, NULL)
#6 /code/web/core/lib/Drupal/Core/TypedData/TypedData.php(132): Drupal\Core\TypedData\Validation\RecursiveValidator->validate(Object(Drupal\Core\Entity\Plugin\DataType\EntityAdapter))
#7 /code/web/core/lib/Drupal/Core/Entity/ContentEntityBase.php(518): Drupal\Core\TypedData\TypedData->validate()
#8 /code/web/core/lib/Drupal/Core/Entity/ContentEntityForm.php(188): Drupal\Core\Entity\ContentEntityBase->validate()
#9 [internal function]: Drupal\Core\Entity\ContentEntityForm->validateForm(Array, Object(Drupal\Core\Form\FormState))
#10 /code/web/core/lib/Drupal/Core/Form/FormValidator.php(82): call_user_func_array(Array, Array)
#11 /code/web/core/lib/Drupal/Core/Form/FormValidator.php(275): Drupal\Core\Form\FormValidator->executeValidateHandlers(Array, Object(Drupal\Core\Form\FormState))
#12 /code/web/core/lib/Drupal/Core/Form/FormValidator.php(118): Drupal\Core\Form\FormValidator->doValidateForm(Array, Object(Drupal\Core\Form\FormState), 'salesforce_mapp...')
#13 /code/web/core/lib/Drupal/Core/Form/FormBuilder.php(593): Drupal\Core\Form\FormValidator->validateForm('salesforce_mapp...', Array, Object(Drupal\Core\Form\FormState))
#14 /code/web/core/lib/Drupal/Core/Form/FormBuilder.php(325): Drupal\Core\Form\FormBuilder->processForm('salesforce_mapp...', Array, Object(Drupal\Core\Form\FormState))
#15 /code/web/core/lib/Drupal/Core/Controller/FormController.php(73): Drupal\Core\Form\FormBuilder->buildForm(Object(Drupal\salesforce_mapping_ui\Form\MappedObjectForm), Object(Drupal\Core\Form\FormState))
#16 /code/web/core/modules/layout_builder/src/Controller/LayoutBuilderHtmlEntityFormController.php(39): Drupal\Core\Controller\FormController->getContentResult(Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\RouteMatch))
#17 [internal function]: Drupal\layout_builder\Controller\LayoutBuilderHtmlEntityFormController->getContentResult(Object(Symfony\Component\HttpFoundation\Request), Object(Drupal\Core\Routing\RouteMatch))
#18 /code/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(123): call_user_func_array(Array, Array)
#19 /code/web/core/lib/Drupal/Core/Render/Renderer.php(627): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#20 /code/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(124): Drupal\Core\Render\Renderer->executeInRenderContext(Object(Drupal\Core\Render\RenderContext), Object(Closure))
#21 /code/web/core/lib/Drupal/Core/EventSubscriber/EarlyRenderingControllerWrapperSubscriber.php(97): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->wrapControllerExecutionInRenderContext(Array, Array)
#22 /code/vendor/symfony/http-kernel/HttpKernel.php(181): Drupal\Core\EventSubscriber\EarlyRenderingControllerWrapperSubscriber->Drupal\Core\EventSubscriber\{closure}()
#23 /code/vendor/symfony/http-kernel/HttpKernel.php(76): Symfony\Component\HttpKernel\HttpKernel->handleRaw(Object(Symfony\Component\HttpFoundation\Request), 1)
#24 /code/web/core/lib/Drupal/Core/StackMiddleware/Session.php(58): Symfony\Component\HttpKernel\HttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#25 /code/web/core/lib/Drupal/Core/StackMiddleware/KernelPreHandle.php(48): Drupal\Core\StackMiddleware\Session->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#26 /code/web/core/lib/Drupal/Core/StackMiddleware/ContentLength.php(28): Drupal\Core\StackMiddleware\KernelPreHandle->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#27 /code/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(106): Drupal\Core\StackMiddleware\ContentLength->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#28 /code/web/core/modules/page_cache/src/StackMiddleware/PageCache.php(85): Drupal\page_cache\StackMiddleware\PageCache->pass(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#29 /code/web/core/lib/Drupal/Core/StackMiddleware/ReverseProxyMiddleware.php(48): Drupal\page_cache\StackMiddleware\PageCache->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#30 /code/web/core/lib/Drupal/Core/StackMiddleware/NegotiationMiddleware.php(51): Drupal\Core\StackMiddleware\ReverseProxyMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#31 /code/web/core/lib/Drupal/Core/StackMiddleware/AjaxPageState.php(36): Drupal\Core\StackMiddleware\NegotiationMiddleware->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#32 /code/web/core/lib/Drupal/Core/StackMiddleware/StackedHttpKernel.php(51): Drupal\Core\StackMiddleware\AjaxPageState->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#33 /code/web/core/lib/Drupal/Core/DrupalKernel.php(704): Drupal\Core\StackMiddleware\StackedHttpKernel->handle(Object(Symfony\Component\HttpFoundation\Request), 1, true)
#34 /code/web/index.php(19): Drupal\Core\DrupalKernel->handle(Object(Symfony\Component\HttpFoundation\Request))
#35 {main}
🇺🇸United States brooke_heaton

Nope. That's not the problem.

See, by setting $create_only to FALSE, you are STILL running a function that should not be ran and results in additional errors.

Warning: Trying to access array offset on value of type null in Drupal\autotagger_search_in_text\Plugin\Autotagger\SearchInTextFields->tagNode() (line 209 of modules/contrib/autotagger/modules/autotagger_search_in_text/src/Plugin/Autotagger/SearchInTextFields.php).
Warning: Trying to access array offset on value of type null in Drupal\autotagger_search_in_text\Plugin\Autotagger\SearchInTextFields->tagNode() (line 210 of modules/contrib/autotagger/modules/autotagger_search_in_text/src/Plugin/Autotagger/SearchInTextFields.php).

We want to wrap this in a conditional and NOT run this if there are no settings on a bundle.

 if ($node->isNew() || !$create_only) {
          // If the node is first being created, or the node is set to not only tag
          // on new, then go ahead and tag it.
            $this->tagNode($node);
        }

If there are no settings on a bundle, why are we tagging the node? The node has no settings and the node is new.

Your ternary is nice and all, but the goal here should be to prevent tagging of nodes that do not have any settings. For that you need a conditional statement to prevent running $this->tagNode if $settings['autotagger_tag_on_create_only'] returns FALSE. BTW Drupal coding standards should have PHP Constants like FALSE in ALL CAPS.

🇺🇸United States brooke_heaton

So I don't think a ternary is possible here. We actually want the entire code below to be conditional and we don't want to run ->tagNode whatsoever if there are no settings. I don't see a way to apply a ternary here, sorry.

 if (isset($settings)) {

      $create_only = $settings['autotagger_tag_on_create_only'];

      if ($node->isNew() || !$create_only) {
        // If the node is first being created, or the node is set to not only tag
        // on new, then go ahead and tag it.
        $this->tagNode($node);
      }
🇺🇸United States brooke_heaton

I removed the module entirely due to this issue. Was not worth the pain nor time.

🇺🇸United States brooke_heaton

For the benefit of others, here's how I was able to get custom attributes/mapping working with drupalauth4ssp.

First, you will need to patch the drupalauth/simplesamlphp-module-drupalauth module required by drupalauth4ssp using this PR. As of Feb 27, 2024 the PR has not yet been integrated. What that PR does is it creates an Event in the drupalauth SSP module to allow for a Drupal EventSubscriber.

Next you will need to create your custom EventSubscriber to subscribe to the SimpleSAML\Module\drupalauth\Event\SetAttributesEvent created with the patch from the PR above.

Below is an example of how I am mapping to First and Last names in Drupal which are created via the 'name' module, which is not accounted for with the out-of-the-box attribute mapping of drupaluth.

 declare(strict_types=1);

namespace Drupal\custom_sso\EventSubscriber;

use Symfony\Component\EventDispatcher\EventSubscriberInterface;
use SimpleSAML\Module\drupalauth\Event\SetAttributesEvent;

/**
 * @todo Add description for this subscriber.
 */
final class CustomSsoSubscriber implements EventSubscriberInterface
{

  /**
   * {@inheritdoc}
   */
    public static function getSubscribedEvents(): array
    {
        $message = "getSubcribedEvents fired";
        return [
        SetAttributesEvent::EVENT_NAME => ['setAttributes'],
        ];
    }

  /**
   * React to attributes
   *
   * @param \SimpleSAML\Module\drupalauth\Event\SetAttributesEvent $event
   *   Drupalauth setAttributes event.
   */
    public function setAttributes(SetAttributesEvent $event)
    {
        $user = $event->getUser();
        if (!$user->get('field_name')->isEmpty()) {
            $first = isset($user->get('field_name')->given) ? $user->get('field_name')->given : NULL;
            $last = isset($user->get('field_name')->family) ? $user->get('field_name')->family : NULL;
            $attributes = $event->getAttributes();
            $attributes['givenName'] = [$first];
            $attributes['sn'] = [$last];
            $event->setAttributes($attributes);
        }
    }
}

🇺🇸United States brooke_heaton

FWIW since the future of this module is undetermined, I have implemented drupalauth4ssp and so far it is working pretty well, however it is lacking some of the features of saml_idp, namely the implementation of a alter hook to manipulate the SimpleSAML 'attributes' in an assertion. But it does seem to have a mechanism to define attributes. I am still investigating. Thanks for your owrk on this @halth.

🇺🇸United States brooke_heaton

Try:

composer require 'drupal/drupalauth4ssp:^2.0@RC'

🇺🇸United States brooke_heaton

I should note that the new requiresments of the module.enable config makes the current README and Drupal\saml_idp\Install::postInstall obsolete. The config-dist should probably include an example config.php file as well.

🇺🇸United States brooke_heaton

Hey folks, been around for a while and trying to follow the transition from patches to MRs but as I'm on Drupal 10.2 I have absolutely no idea which patch or MR I should be using for this. Can anyone advise?

🇺🇸United States brooke_heaton

Patch #14 is applying clean for me and working. Thanks @paulrad!

🇺🇸United States brooke_heaton

It's odd that this fix is not in the latest version marked as compatibel with Drupal 10. The latest version is most definitely not compatible without this.

🇺🇸United States brooke_heaton

Just here to report that I am seeing the same errors as noted in $6. I see the following error on my search View:

can not use FieldCache on unindexed field: boost_documenttype Status reportmessage can not use FieldCache on unindexed field: boost_documentdescription The request sent by the client was syntactically incorrect.

I am using the following modules on Drupal 9.5.11:

Search API (search_api) 8.x-1.30
Search API Pantheon (search_api_pantheon) 8.1.4
Search API Solr Autocomplete (search_api_solr_autocomplete) 4.2.9
Search API Solr Legacy (search_api_solr_legacy) 4.2.9
Search API Solr (search_api_solr) 4.2.9

🇺🇸United States brooke_heaton

The latest patch isn't resolving the fundamental performance problems for me. The views plugin still appears to try to load WAY WAY too many entities. In my case I'm using nodes referenced on a Paragraph that uses a Relationship. What DOES work for me is to comment out the getValueOptions() function entirely when developing locally. I think the plugin has some fundamental problems that aren't addressed here. Definitely needs a lot more work.

🇺🇸United States brooke_heaton

Patch at 💬 D9 compatibility issues Needs work is prerequisite for this patch and does not apply clean, so this patch cannot be applied.

🇺🇸United States brooke_heaton

I am unable to get this patch to apply clean against 8.x-1.x-dev and this patch is a prerequisite of 💬 Drupal 10 compatibility Needs review so I am unable to get a Drupal 10 compatible version of this module.

🇺🇸United States brooke_heaton

I added an isset check to all elemenets of the options array and this has resolved my issue.

🇺🇸United States brooke_heaton

That fix seems to have worked, buit now I'm getting this error. This seems to be a problem with not having settings initially for all options across the board:

Warning: Undefined array key "mode" in /app/web/modules/contrib/tiny_slider/src/Plugin/views/style/TinySlider.php

🇺🇸United States brooke_heaton

The MR failed and the patch is not applying to 1.1.x-dev.

🇺🇸United States brooke_heaton

If you are looking to upgrade from D9 to D10, this is the issue/patch that I used. I was not able to immediately upgrade to D10 without a working module compatible with both D9 and D10. I did not use the 3.x nor 4.x branches as they were not dual compatible with D9 and D10 for the upgrade path.

🇺🇸United States brooke_heaton

I am also having similar issues. Trying to install with composer, having followed the instructions on the module page, I am now getting this error:

drupal/entity_relationship_diagram 2.0.0-alpha1 requires npm-asset/viz-js--viz ^3 -> could not be found in any version, there may be a typo in the package name.

🇺🇸United States brooke_heaton

The tip in #9 helped me get this working in composer.json. Thanks @j.b.

🇺🇸United States brooke_heaton

I can confirm that patch #25 applies clean and upgrade_status no longer triggers an issue.

🇺🇸United States brooke_heaton

Changing version to 2.0.0. I think we just need a stable release compatible with 10 since only the Dev version currently is.

🇺🇸United States brooke_heaton

I'm updating to Drupal 10 and am now getting this error after using this patch:

PHP Fatal error:  Uncaught Error: Class "Twig_Extension" not found in /app/docroot/modules/contrib/profile/src/TwigExtension/ProfileExtension.php:10
Stack trace:
🇺🇸United States brooke_heaton

I think the issue is that it is only the Dev version that is currently Drupal 10 compatible. It's probably good to put out a stable Drupal 10 compatible release.

🇺🇸United States brooke_heaton

@abhishek_virasat Upgrade Status shows it as 'Unchecked' in your scan.

I'm using version 2.0.0 which clearly shows in the .info file that this module is only compatible with 8.x and ^9

name: 'Field IP address'
type: module
description: 'Provides a field to hold single or range of IPs (IPv4 or IPv6).'
package : Field types
core: 8.x
core_version_requirement: 8.x || ^9
dependencies:
  - field

# Information added by Drupal.org packaging script on 2021-03-08
version: '2.0.0'
project: 'field_ipaddress'
datestamp: 1615227158
🇺🇸United States brooke_heaton

This fix somehow disappeared. This is not in version 5.

🇺🇸United States brooke_heaton

I'm unclear on if this functionality made it to version 5.0.x. I have a Paragraph type in Drupal 9 that is related to a User (Parent ID would be user ID). I'm unable to expose this relationship when mapping the Paragraph to a Custom Object on Salesforce. I see all other Entity Reference fields, including the Paragraph Type, but not the Parent ID. Is this functionality not in version 5?

🇺🇸United States brooke_heaton

In theory, exposting Routes to Views might best be done in Core but for now, this gets us there.

🇺🇸United States brooke_heaton

Here's a patch to add Views integration. It might be good to also add a default config that adds a default view rather than the static report.

🇺🇸United States brooke_heaton

This module is useful and could use some help. I'm happy to take this over to upgrade to Drupal 9/10 compliance.

🇺🇸United States brooke_heaton

@rosemarystanley Wow, thanks so much! I'll review this out ASAP!

🇺🇸United States brooke_heaton

So, I guess I'm continually confused - I apologize. I was able to get things set up once again on our Dev site but see that the tokens state:

Last token was generated at 02/06/2023 02:57 pm and expires on 02/06/2023 04:57 pm.

So, evidently these tokens are only good for 2 hours? Is that the case? Is there something that I am missing here? Are these to be refreshed on a cron job? Per the documentation, I have set 'auth_type' => 'auth_code' in Settings.php - is this correct?

🇺🇸United States brooke_heaton

Got it - just a heads up that the documentation that you refer to above still recommneds using "Rotating Refresh Tokens" which might be where I went wrong. There's a note below to use "Long Lived Refresh Tokens" but this contradicts the guidance right above. I think that just confused me. I'm still working to get this set up. It was working at one point then stopped after a deployment. We had this problem in the past.

🇺🇸United States brooke_heaton

We evidently did not have long-lived tokens set up - I see now that we must use them. I'm a bit unclear on when and how often the refresh_token would be regenerated. This value is saved in configuration and if we then commit this configuration to our repository, wouldn't that pose a risk that it would break the credentials? Is this something that you would advise keeping codified in our repository? Or would the practice be to use config_ignore to not overwrite this value if it is later regnerated?

🇺🇸United States brooke_heaton

I agree that this is desperately needed!

Production build 0.69.0 2024