adamfranco β changed the visibility of the branch 2.3.x to hidden.
adamfranco β changed the visibility of the branch 3.0.x to hidden.
adamfranco β changed the visibility of the branch 3397021-entitymappings-phpstan-2.3.x to active.
adamfranco β changed the visibility of the branch 3397021-entitymappings-phpstan-2.3.x to hidden.
I tried the attached patch, but was still getting the error "'htmlpurifier_configuration' is not a supported key." when trying to save my text format in Drupal 10.3.2. This seems to be due to a missing schema file in the module. The attached patch includes the changes from #14 and adds a config/schema/htmlpurifier.schema.yml
file that identifies htmlpurifier_configuration
as a valid key for the filter settings.
With this change, the HTMLPurifier filter can be enabled with CKEditor 5 as the editor and the configuration form successfully saved.
I can confirm that patch #4 works well and has solved my issue. Our large sites have dozens of menus, blocks, and paragraphs on most pages and these combine to raw un-minified Surrogate-Key lengths of well over 25,000 characters for 390 separate cache-tags. This patch brings that header size down to under 2,000 bytes.
adamfranco β created an issue.
adamfranco β created an issue.
@jonathanshaw, there's a typo in Merge request 11 on lines 132-133 of advancedqueue.install
. The variable initialized is $schema
but undefined $database_schema
name is used. See attached patch.
Attached is a patch to fix the argument type for $format parameter to match that used by libphonenumber\PhoneNumberFormat
(string --> int).
After this patch PHPStan reports only more minor errors:
vendor/bin/phpstan analyze --level 5 ../drupal-other/telephone_formatter/
5/5 [ββββββββββββββββββββββββββββ] 100%
------ -----------------------------------------------------------------------------------------
Line drupal-other/telephone_formatter/src/Plugin/Field/FieldFormatter/TelephoneFormatter.php
------ -----------------------------------------------------------------------------------------
77 Unsafe usage of new static().
π‘ See: https://phpstan.org/blog/solving-phpstan-error-unsafe-usage-of-new-static
184 Access to an undefined property Drupal\Core\Field\FieldItemInterface::$value.
π‘ Learn more: https://phpstan.org/blog/solving-phpstan-access-to-undefined-property
222 Access to an undefined property Drupal\Core\Field\FieldItemInterface::$value.
π‘ Learn more: https://phpstan.org/blog/solving-phpstan-access-to-undefined-property
250 Access to an undefined property Drupal\Core\Field\FieldItemInterface::$value.
π‘ Learn more: https://phpstan.org/blog/solving-phpstan-access-to-undefined-property
------ -----------------------------------------------------------------------------------------
------ -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Line drupal-other/telephone_formatter/tests/src/Functional/FieldFormatterTest.php
------ -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
15 Drupal\Tests\BrowserTestBase::$defaultTheme is required. See https://www.drupal.org/node/3083055, which includes recommendations on which theme to use.
22 PHPDoc type array of property Drupal\Tests\telephone_formatter\Functional\FieldFormatterTest::$modules is not covariant with PHPDoc type array<string> of overridden property Drupal\Tests\BrowserTestBase::$modules.
π‘ You can fix 3rd party PHPDoc types with stub files:
π‘ https://phpstan.org/user-guide/stub-files
------ -----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
[ERROR] Found 6 errors
adamfranco β created an issue.
adamfranco β created an issue.
adamfranco β created an issue.
For anyone looking for a workaround while waiting for this to be fixed, here's the setup I'm using based on the BufferingLogger and tying it to my logger channel.
mymodule/tests/Kernel/MyModuleTestBase.php
namespace Drupal\Tests\mymodule\Kernel;
use Drupal\Core\DependencyInjection\ContainerBuilder;
use Drupal\Core\Logger\RfcLogLevel;
use Drupal\KernelTests\Core\Entity\EntityKernelTestBase;
use Symfony\Component\ErrorHandler\BufferingLogger;
/**
* Base class for setting up MyModule tests.
*
* @group mymodule
*/
abstract class MyModuleTestBase extends EntityKernelTestBase {
/**
* The entity type manager service.
*
* @var \Psr\Log\LoggerInterface
*/
protected $logger;
/**
* {@inheritdoc}
*/
public function register(ContainerBuilder $container) {
parent::register($container);
$container
->register('logger.channel.mymodule', BufferingLogger::class)
->addTag('logger');
}
/**
* {@inheritdoc}
*/
protected function setUp(): void {
parent::setUp();
$this->logger = $this->container->get('logger.channel.mymodule');
// Clean any existing logs.
$this->logger->cleanLogs();
}
/**
* Verify that no logs were written worse than a certain level.
*
* @param string $minLogLevel
* The RfcLogLevel name that is the minimum allowed. One of:
* EMERGENCY, ALERT, CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG
* @param string $message
* An optional message to print.
*
* @return array
* The logs in our logger for further examination.
*/
protected function assertNoLogsWorseThan(string $minLogLevel, string $message = NULL): array {
$logs = $this->logger->cleanLogs();
$rfcLogLevels = new \ReflectionClass(RfcLogLevel::class);
$minLogLevelText = strtoupper(trim($minLogLevel));
$this->assertContains($minLogLevelText, array_keys($rfcLogLevels->getConstants()), "\$this->assertLogsNoWorseThan(\$minLogLevel): \$minLogLevel=$minLogLevel is not one of ".implode(", ", array_keys($rfcLogLevels->getConstants())));
$minLogLevelInt = $rfcLogLevels->getConstant($minLogLevelText);
foreach ($logs as [$level, $message, $context]) {
$level = trim($level);
$logLevelText = strtoupper($level);
$logLevelInt = $rfcLogLevels->getConstant($logLevelText);
$this->assertGreaterThanOrEqual($minLogLevelInt, $logLevelInt, "Log worse than $minLogLevel recorded: [$level] ".$this->getLogMessage($level, $message, $context));
}
return $logs;
}
/**
* Assert that a log matching the level and regular expression exists.
*
* @param string $level
* The RfcLogLevel name that is the minimum allowed. One of:
* EMERGENCY, ALERT, CRITICAL, ERROR, WARNING, NOTICE, INFO, DEBUG
* @param string $regex
* A regular expression to log.
* @param array $logs
* An optional array of logs to examine for multiple checks. If not passed
* logs will be cleared from the logger.
* @param string $message
* An optional message to print.
*
* @return array
* The logs in our logger for further examination.
*/
protected function assertLogsMatchingRegex(string $level, string $regex, $logs = NULL, string $message = NULL): array {
if (!is_array($logs)) {
$logs = $this->logger->cleanLogs();
}
$found = FALSE;
$messages = [];
foreach ($logs as [$logLevel, $logMessage, $logContext]) {
$messages[] = $logLevel . "\t" . $logMessage;
if (strtolower($logLevel) == strtolower($level) && preg_match($regex, strval($logMessage))) {
$found = TRUE;
break;
}
}
if ($message) {
$this->assertTrue($found, $message);
}
else {
$this->assertTrue($found, "Expected a message of level $level matching $regex but didn't find one in:\n\t" . implode("\n\t", $messages));
}
return $logs;
}
/**
* Answer message string from a BufferingLogger entry.
*
* Copied from BufferingLogger::__destruct().
*
* @param string $level
* The log level string.
* @param string $message
* The message with placeholders.
* @param array $context
* An array of placeholders to place in the message.
*
* @return string
* The formatted output.
*/
public function getLogMessage($level, $message, $context) {
if (str_contains($message, '{')) {
foreach ($context as $key => $val) {
if (null === $val || \is_scalar($val) || (\is_object($val) && \is_callable([$val, '__toString']))) {
$message = str_replace("{{$key}}", $val, $message);
} elseif ($val instanceof \DateTimeInterface) {
$message = str_replace("{{$key}}", $val->format(\DateTimeInterface::RFC3339), $message);
} elseif (\is_object($val)) {
$message = str_replace("{{$key}}", '[object '.get_debug_type($val).']', $message);
} else {
$message = str_replace("{{$key}}", '['.\gettype($val).']', $message);
}
}
}
return $message;
}
}
Then in my kernel tests I can execute some code and then something like:
$this->assertNoLogsWorseThan('debug');
Which will result in an error like:
Log worse than debug recorded: [info] person: Created jdoe@middlebury.edu 00000001. User 1
Failed asserting that 6 is equal to 7 or is greater than 7.
If I need to examine logs more closely to look for an expected warning message, I can use something like:
// Ensure that a warning about our conflict was logged.
$logs = $this->assertNoLogsWorseThan('warning');
$this->assertLogsMatchingRegex('warning', '/^Error syncing person\. ID: 00000009/', $logs);
Which will result in an error message like the following:
Expected a message of level warning matching /^Error syncing person\. PIDM: 00000009/ but didn't find one in:
info person: Created jdoe@middlebury.edu 00000001. User 1
warning Error syncing person. PIDM: 00000002 Error: Found an existing account matching name or mail=jdoe@middlebury.edu [1] that was created during the past year. Skipping auto-rename of old account.
info person: Created rjones@middlebury.edu 00000003. User 2
info person: Created ldoe@middlebury.edu 00000004. User 3
info person: Synced all people. 4 total, 3 changed, 1 failed.
This isn't completely generalized and has the ugly need to pass logs to do multiple checks, but the DX isn't terrible in my actual tests.
That is is what this module does. See the README for installation instructions.
If you are using webform, the audiorecorder_webform_integration submodule exposes this control for usage in webform fields.
Thanks for the patch and review! Fixed in https://git.drupalcode.org/project/audiorecorder/-/commit/247b0024f7b232... and will be included in the pending 1.0.0 release (as soon as #3352502: [1.x] Audio Recorder Widget β gets reviewed/approved which will allow me to include the 1.0.0 release in the security advisory program).
I think I may have found the issue. We should probably use the default validation provided by
Drupal\file\Element\ManagedFile
if at all possible, but an empty validation function was added that prevents that default validation from happening. I removed this empty function in https://git.drupalcode.org/project/audiorecorder/-/commit/fc82d175f872d7... which I hope addresses the issue.
Thanks for the review, @vishal.kadam! I've updated the 1.x branch with fixes to each of the items you pointed out.
I left one of comments in place because it isn't a direct copy of the parent function's doc and explains more about it's particulars:
FILE: src/Plugin/Field/FieldWidget/AudioRecorderWidget.php
/**
* Form API callback: Processes a file_audio_recorder field element.
*
* Expands the file_audio_recorder type to include the max_recording_time.
*
* This method is assigned as a #process callback in formElement() method.
*/
public static function process($element, FormStateInterface $form_state, $form) {
The others have been converted to {@inheritdoc}
.
In addition to other possible changes, it is likely that FileWidget::formMultipleElements()
and FileWidget::processMultiple()
will need to be overridden to support recording multiple audio files.
adamfranco β created an issue.
adamfranco β created an issue.
Closing as fixed now that it is included in 1.0.0-rc1 β .
Closing as fixed now that it is included in 1.0.0-rc1 β .
Closing as fixed now that it is included in 1.0.0-rc1 β .
Closing as fixed now that it is included in 1.0.0-rc1 β .
Closing as fixed now that it is included in 1.0.0-rc1 β .
Closing as fixed now that it is included in 1.0.0-rc1 β .
I tried testing this patch on empty installations of Drupal 9.5.7 and 10.1.x-dev and neither works successfully in the default Claro theme.
The default multiple-file-upload UI in D9 & D10 uses an upload widget and then adds the uploaded files to a sortable table:
When the Audio Recorder widget is used in D10 instead of the default file widget the first audio file is recorded, but it is never shifted to a sortable table and there is not a mechanism to add a second recording:
This behavior is the same as without this patch in D10.
In D9 in contrast, the first recording is saved and then the UI dissapears and a second recording can be made, but there is no indication of the first recording existing:
Without this patch in D9 the behavior is that the single file is recorded and then left in place with no option to add another (similar to the D10 state with or without this patch).
I haven't dived into the default File widget to understand how it works and which parts would be good to override or re-implement in the audio-recorder widget to get a similar behavior with multiple recordings with just the actual upload part (and file link-vs-audio-player) replaced.
Thanks for reporting this. My apologies for the delay. It is now fixed in https://git.drupalcode.org/project/audiorecorder/-/commit/a02ba1e3fe267e...
Thanks for the patch! This is fixed in https://git.drupalcode.org/project/audiorecorder/-/commit/d517ee848e34fa...
Thanks for the patch and review! Fixed in https://git.drupalcode.org/project/audiorecorder/-/commit/79009f952ddf7d...
Thanks Jacob. Added in https://git.drupalcode.org/project/audiorecorder/-/commit/c3ba2e4e600dc1...
Note that using core/once
requires dropping D8 support (not a big deal) which is removed in https://git.drupalcode.org/project/audiorecorder/-/commit/96bbd383094743...
adamfranco β created an issue.