Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
27 changes: 27 additions & 0 deletions core/Command/SetupChecks.php
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,29 @@ protected function configure(): void {
;
}

/**
* @TODO move this method to a common service used by notifications, activity and this command
* @throws \InvalidArgumentException if a parameter has no name or no type
*/
private function richToParsed(string $message, array $parameters): string {
$placeholders = [];
$replacements = [];
foreach ($parameters as $placeholder => $parameter) {
$placeholders[] = '{' . $placeholder . '}';
foreach (['name','type'] as $requiredField) {
if (!isset($parameter[$requiredField]) || !is_string($parameter[$requiredField])) {
throw new \InvalidArgumentException("Invalid rich object, {$requiredField} field is missing");
}
}
$replacements[] = match($parameter['type']) {
'user' => '@' . $parameter['name'],
'file' => $parameter['path'] ?? $parameter['name'],
default => $parameter['name'],
};
}
return str_replace($placeholders, $replacements, $message);
}

protected function execute(InputInterface $input, OutputInterface $output): int {
$results = $this->setupCheckManager->runAll();
switch ($input->getOption('output')) {
Expand All @@ -70,6 +93,10 @@ protected function execute(InputInterface $input, OutputInterface $output): int
};
$verbosity = ($check->getSeverity() === 'error' ? OutputInterface::VERBOSITY_QUIET : OutputInterface::VERBOSITY_NORMAL);
$description = $check->getDescription();
$descriptionParameters = $check->getDescriptionParameters();
if ($description !== null && $descriptionParameters !== null) {
$description = $this->richToParsed($description, $descriptionParameters);
}
$output->writeln(
"\t\t".
($styleTag !== null ? "<{$styleTag}>" : '').
Expand Down
25 changes: 25 additions & 0 deletions core/js/setupchecks.js
Original file line number Diff line number Diff line change
Expand Up @@ -380,6 +380,28 @@
return deferred.promise();
},

/**
* @param message The message string containing placeholders.
* @param parameters An object with keys as placeholders and values as their replacements.
*
* @return The message with placeholders replaced by values.
*/
richToParsed: function (message, parameters) {
for (var [placeholder, parameter] of Object.entries(parameters)) {
var replacement;
if (parameter.type === 'user') {
replacement = '@' + parameter.name;
} else if (parameter.type === 'file') {
replacement = parameter.path || parameter.name;
} else {
replacement = parameter.name;
}
message = message.replace('{' + placeholder + '}', replacement);
}

return message;
},

addGenericSetupCheck: function(data, check, messages) {
var setupCheck = data[check] || { pass: true, description: '', severity: 'info', linkToDoc: null}

Expand All @@ -391,6 +413,9 @@
}

var message = setupCheck.description;
if (setupCheck.descriptionParameters) {
message = this.richToParsed(message, setupCheck.descriptionParameters);
}
if (setupCheck.linkToDoc) {
message += ' ' + t('core', 'For more details see the {linkstart}documentation ↗{linkend}.')
.replace('{linkstart}', '<a target="_blank" rel="noreferrer noopener" class="external" href="' + setupCheck.linkToDoc + '">')
Expand Down
40 changes: 32 additions & 8 deletions lib/public/SetupCheck/SetupResult.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,8 @@

namespace OCP\SetupCheck;

use OCP\RichObjectStrings\IValidator;

/**
* @brief This class is used for storing the result of a setup check
*
Expand All @@ -46,52 +48,62 @@ class SetupResult implements \JsonSerializable {
* @brief Private constructor, use success()/info()/warning()/error() instead
* @param self::SUCCESS|self::INFO|self::WARNING|self::ERROR $severity
* @since 28.0.0
* @since 28.0.2 Optional parameter ?array $descriptionParameters
* @since 28.0.2 throws \OCP\RichObjectStrings\InvalidObjectExeption
*/
private function __construct(
private string $severity,
private ?string $description = null,
private ?array $descriptionParameters = null,
private ?string $linkToDoc = null,
) {
if ($description !== null && $descriptionParameters !== null) {
\OCP\Server::get(IValidator::class)->validate($description, $descriptionParameters);
}
}

/**
* @brief Create a success result object
* @param ?string $description Translated detailed description to display to the user
* @param ?string $linkToDoc URI of related relevent documentation, be it from Nextcloud or another project
* @since 28.0.0
* @since 28.0.2 Optional parameter ?array $descriptionParameters
*/
public static function success(?string $description = null, ?string $linkToDoc = null): self {
return new self(self::SUCCESS, $description, $linkToDoc);
public static function success(?string $description = null, ?string $linkToDoc = null, ?array $descriptionParameters = null): self {
return new self(self::SUCCESS, $description, $descriptionParameters, $linkToDoc);
}

/**
* @brief Create an info result object
* @param ?string $description Translated detailed description to display to the user
* @param ?string $linkToDoc URI of related relevent documentation, be it from Nextcloud or another project
* @since 28.0.0
* @since 28.0.2 Optional parameter ?array $descriptionParameters
*/
public static function info(?string $description = null, ?string $linkToDoc = null): self {
return new self(self::INFO, $description, $linkToDoc);
public static function info(?string $description = null, ?string $linkToDoc = null, ?array $descriptionParameters = null): self {
return new self(self::INFO, $description, $descriptionParameters, $linkToDoc);
}

/**
* @brief Create a warning result object
* @param ?string $description Translated detailed description to display to the user
* @param ?string $linkToDoc URI of related relevent documentation, be it from Nextcloud or another project
* @since 28.0.0
* @since 28.0.2 Optional parameter ?array $descriptionParameters
*/
public static function warning(?string $description = null, ?string $linkToDoc = null): self {
return new self(self::WARNING, $description, $linkToDoc);
public static function warning(?string $description = null, ?string $linkToDoc = null, ?array $descriptionParameters = null): self {
return new self(self::WARNING, $description, $descriptionParameters, $linkToDoc);
}

/**
* @brief Create an error result object
* @param ?string $description Translated detailed description to display to the user
* @param ?string $linkToDoc URI of related relevent documentation, be it from Nextcloud or another project
* @since 28.0.0
* @since 28.0.2 Optional parameter ?array $descriptionParameters
*/
public static function error(?string $description = null, ?string $linkToDoc = null): self {
return new self(self::ERROR, $description, $linkToDoc);
public static function error(?string $description = null, ?string $linkToDoc = null, ?array $descriptionParameters = null): self {
return new self(self::ERROR, $description, $descriptionParameters, $linkToDoc);
}

/**
Expand All @@ -113,6 +125,17 @@ public function getDescription(): ?string {
return $this->description;
}

/**
* @brief Get the description parameters for the setup check result
*
* If this returns null, description must not be treated as rich text
*
* @since 28.0.2
*/
public function getDescriptionParameters(): ?array {
return $this->descriptionParameters;
}

/**
* @brief Get the name for the setup check
*
Expand Down Expand Up @@ -150,6 +173,7 @@ public function jsonSerialize(): array {
'name' => $this->name,
'severity' => $this->severity,
'description' => $this->description,
'descriptionParameters' => $this->descriptionParameters,
'linkToDoc' => $this->linkToDoc,
];
}
Expand Down