Problem/Motivation
When attempting to use this module with PHP 8.1 and a custom endpoint, I'm getting the following error:
TypeError: Drupal\jsonrpc\Controller\HttpController::aggregateResponseHeaders(): Argument #1 ($rpc_responses) must be of type array, null given, called in /app/web/modules/contrib/jsonrpc/src/Controller/HttpController.php on line 133 in Drupal\jsonrpc\Controller\HttpController->aggregateResponseHeaders() (line 303 of modules/contrib/jsonrpc/src/Controller/HttpController.php).
Steps to reproduce
Here's my Method **CancelUserAccount.php**:
<?php
namespace Drupal\mymodule\Plugin\jsonrpc\Method;
use Drupal\Core\Logger\LoggerChannelFactory;
use Drupal\Core\Session\AccountInterface;
use Drupal\jsonrpc\MethodInterface;
use Drupal\jsonrpc\Object\ParameterBag;
use Drupal\jsonrpc\Plugin\JsonRpcMethodBase;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Provides a way for the logged-in use to cancel the user's account.
*
* @JsonRpcMethod(
* id = "user.cancel",
* usage = @Translation("Cancels the logged-in user's account."),
* access = {"cancel account"},
* ),
*/
class CancelUserAccount extends JsonRpcMethodBase {
/**
* {@inheritdoc}
*/
public function execute(ParameterBag $params) {
$uid = $this->currentUser->id();
// Make sure that we do not try to cancel user 1 or anonymous.
if ($uid !== 1 && $uid !== 0) {
$user_storage = \Drupal::entityTypeManager()->getStorage('user');
// $user_storage = $this->entityTypeManager->getStorage('user');
$current_user = $user_storage->load($uid);
// See: https://drupal.stackexchange.com/a/204422.
// Send the user the "account blocked" confirmation email.
_user_mail_notify('status_blocked', $current_user);
$current_user->set('status', FALSE);
$current_user->save();
$this->loggerFactory->notice("User account for UID @uid cancelled by JSON RPC.", [
'@uid' => $current_user->id(),
]);
return TRUE;
}
return FALSE;
}
/**
* {@inheritdoc}
*/
public static function outputSchema() {
return NULL;
// return ['type' => 'string'];
}
/**
* The current user account.
*
* @var \Drupal\Core\Session\AccountInterface
*/
protected AccountInterface $currentUser;
/**
* Logger factory.
*
* @var \Drupal\Core\Logger\LoggerChannelFactory
*/
protected $loggerFactory;
/**
* Constructs a new EntityResourceBase object.
*
* @param array $configuration
* JSON-RPC config.
* @param string $plugin_id
* The plugin ID.
* @param \Drupal\jsonrpc\MethodInterface $plugin_definition
* The plugin definition.
* @param \Drupal\Core\Session\AccountInterface $account
* The current user.
* @param \Drupal\Core\Logger\LoggerChannelFactory $logger_factory
* The Watchdog logger.
*/
public function __construct(array $configuration, string $plugin_id, MethodInterface $plugin_definition, AccountInterface $account, LoggerChannelFactory $logger_factory) {
parent::__construct($configuration, $plugin_id, $plugin_definition);
$this->currentUser = $account;
$this->loggerFactory = $logger_factory->get('mymodule');
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static(
$configuration, $plugin_id, $plugin_definition,
$container->get('current_user'),
$container->get('logger.factory'),
);
}
}
Proposed resolution
In HttpController.php:
try {
$rpc_responses = $this->getRpcResponses($rpc_requests);
// Aggregate the response headers so we can add them to the HTTP response.
$header_bag = $this->aggregateResponseHeaders($rpc_responses);
// If no RPC response(s) were generated (happens if all of the request(s)
// were notifications), then return a 204 HTTP response.
if (empty($rpc_responses)) {
$response = CacheableJsonResponse::create(NULL, Response::HTTP_NO_CONTENT);
$response->headers->add($header_bag->all());
return $response;
}
The problem here is that getRpcResponses() returns Response[]|null, but aggregateResponseHeaders() has an array typehint, so if getRpcResponses returns null, then the error occurs.
I'm not sure how to fix this though because if $rpc_responses is NULL, then it needs $header_bag in the if (empty($rpc_responses)), but $header_bag hasn't been generated because $rpc_responses is null.
Remaining tasks
User interface changes
API changes
Data model changes