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
2 changes: 1 addition & 1 deletion .env
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ VORTEX_NOTIFY_EMAIL_FROM=webmaster@your-site-domain.example
# Multiple names can be specified as a comma-separated list of email addresses
# with optional names in the format "email|name".
# Example: "to1@example.com|Jane Doe, to2@example.com|John Doe"
VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@your-site-domain.example
VORTEX_NOTIFY_EMAIL_RECIPIENTS="webmaster@your-site-domain.example|Webmaster"

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Drop unnecessary quotes to satisfy dotenv-linter

The value has no spaces; quotes aren’t needed and trigger QuoteCharacter warning.

Apply:

-VORTEX_NOTIFY_EMAIL_RECIPIENTS="webmaster@your-site-domain.example|Webmaster"
+VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@your-site-domain.example|Webmaster
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
VORTEX_NOTIFY_EMAIL_RECIPIENTS="webmaster@your-site-domain.example|Webmaster"
VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@your-site-domain.example|Webmaster
🧰 Tools
🪛 dotenv-linter (3.3.0)

[warning] 251-251: [QuoteCharacter] The value has quote characters (', ")

(QuoteCharacter)

🤖 Prompt for AI Agents
In .env around line 251, the value VORTEX_NOTIFY_EMAIL_RECIPIENTS is surrounded
by unnecessary double quotes which triggers a dotenv-linter QuoteCharacter
warning; remove the surrounding quotes so the line becomes
VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@your-site-domain.example|Webmaster (no
leading/trailing whitespace or quotes) to satisfy the linter.

#;> NOTIFICATIONS

#;< DEMO
Expand Down
2 changes: 1 addition & 1 deletion .vortex/docs/content/workflows/variables.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -1319,7 +1319,7 @@ Applies to email notifications.

Multiple names can be specified as a comma-separated list of email addresses<br/>with optional names in the format "email|name".<br/>Example: "to1@example.com|Jane Doe, to2@example.com|John Doe"

Default value: `webmaster@your-site-domain.example`
Default value: `webmaster@your-site-domain.example|Webmaster`

Defined in: `.env`, `scripts/vortex/notify-email.sh`

Expand Down
4 changes: 2 additions & 2 deletions .vortex/installer/src/Command/InstallCommand.php
Original file line number Diff line number Diff line change
Expand Up @@ -397,7 +397,7 @@ protected function header(): void {
EOT;

$logo = Tui::terminalWidth() >= 80 ? $logo_large : $logo_small;
$logo = Tui::center($logo, min(Tui::terminalWidth(), 80), '─');
$logo = Tui::center($logo, Tui::terminalWidth(), '─');
$logo = Tui::cyan($logo);

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Reuse computed terminal width and guard math

Avoid multiple Tui::terminalWidth() calls and ensure non-negative padding.

-    $logo = Tui::center($logo, Tui::terminalWidth(), '─');
+    $tw = Tui::terminalWidth();
+    $logo = Tui::center($logo, $tw, '─');
@@
-    $logo .= PHP_EOL . Tui::dim(str_pad(sprintf('Installer version: %s', $version), Tui::terminalWidth() - 2, ' ', STR_PAD_LEFT));
+    $logo .= PHP_EOL . Tui::dim(str_pad(sprintf('Installer version: %s', $version), max(0, $tw - 2), ' ', STR_PAD_LEFT));

Also applies to: 413-414

🤖 Prompt for AI Agents
In .vortex/installer/src/Command/InstallCommand.php around lines 401 and also
lines 413-414, the code calls Tui::terminalWidth() multiple times and computes
padding without guarding against negative values; refactor to call
Tui::terminalWidth() once into a local variable, reuse that variable for all
width calculations, and clamp any computed padding to a minimum of 0 (e.g.,
max(0, computedPadding)) before using it so you never pass negative padding to
string functions or styling calls.


$version = $this->getApplication()->getVersion();
Expand All @@ -410,7 +410,7 @@ protected function header(): void {
$version = str_replace('@vortex-installer-version@', 'development', $version);
}

$logo .= PHP_EOL . Tui::dim(str_pad(sprintf('Installer version: %s', $version), min(Tui::terminalWidth(), 80) - 2, ' ', STR_PAD_LEFT));
$logo .= PHP_EOL . Tui::dim(str_pad(sprintf('Installer version: %s', $version), Tui::terminalWidth() - 2, ' ', STR_PAD_LEFT));

Tui::note($logo);

Expand Down
2 changes: 1 addition & 1 deletion .vortex/installer/src/Prompts/Handlers/Starter.php
Original file line number Diff line number Diff line change
Expand Up @@ -141,7 +141,7 @@ public function postInstall(): ?string {

// @todo Update to use separate steps for hosting and CI/CD configuration.
$output .= 'Setup integration with your hosting and CI/CD providers:' . PHP_EOL;
$output .= ' See https://www.vortextemplate.com/docs/quickstart';
$output .= ' See https://www.vortextemplate.com/docs/getting-started/installation';
$output .= PHP_EOL;

return $output;
Expand Down
32 changes: 18 additions & 14 deletions .vortex/installer/src/Prompts/Handlers/Tools.php
Original file line number Diff line number Diff line change
Expand Up @@ -67,17 +67,14 @@ public function discover(): null|string|bool|array {

$tools = [];

$cj = JsonManipulator::fromFile($this->dstDir . '/composer.json');
if ($cj instanceof JsonManipulator) {
foreach (static::getToolDefinitions('tools') as $tool => $config) {
if (isset($config['present']) && $config['present'] instanceof \Closure && $config['present']->bindTo($this)()) {
$tools[] = $tool;
}
foreach (static::getToolDefinitions('tools') as $tool => $config) {
if (isset($config['present']) && $config['present'] instanceof \Closure && $config['present']->bindTo($this)()) {
$tools[] = $tool;
}

sort($tools);
}

sort($tools);

return $tools;
}

Expand Down Expand Up @@ -184,7 +181,8 @@ public static function getToolDefinitions(string $filter = 'all'): array {
'present' => function (): mixed {
return File::contains($this->dstDir . '/composer.json', 'dealerdirect/phpcodesniffer-composer-installer') ||
File::contains($this->dstDir . '/composer.json', 'drupal/coder') ||
File::contains($this->dstDir . '/composer.json', 'squizlabs/php_codesniffer');
File::contains($this->dstDir . '/composer.json', 'squizlabs/php_codesniffer') ||
File::exists($this->dstDir . '/phpcs.xml');
},
'composer.json' => function (JsonManipulator $cj): void {
$cj->removeSubNode('require-dev', 'dealerdirect/phpcodesniffer-composer-installer');
Expand All @@ -203,7 +201,8 @@ public static function getToolDefinitions(string $filter = 'all'): array {
'title' => 'PHPStan',
'present' => function (): mixed {
return File::contains($this->dstDir . '/composer.json', 'phpstan/phpstan') ||
File::contains($this->dstDir . '/composer.json', 'mglaman/phpstan-drupal');
File::contains($this->dstDir . '/composer.json', 'mglaman/phpstan-drupal') ||
File::exists($this->dstDir . '/phpstan.neon');
},
'composer.json' => function (JsonManipulator $cj): void {
$cj->removeSubNode('require-dev', 'phpstan/phpstan');
Expand All @@ -220,7 +219,9 @@ public static function getToolDefinitions(string $filter = 'all'): array {
self::RECTOR => [
'title' => 'Rector',
'present' => function (): mixed {
return File::contains($this->dstDir . '/composer.json', 'rector/rector');
return File::contains($this->dstDir . '/composer.json', 'rector/rector') ||
File::contains($this->dstDir . '/composer.json', 'palantirnet/drupal-rector') ||
File::exists($this->dstDir . '/rector.php');
},
'composer.json' => function (JsonManipulator $cj): void {
$cj->removeSubNode('require-dev', 'rector/rector');
Expand All @@ -233,7 +234,8 @@ public static function getToolDefinitions(string $filter = 'all'): array {
self::PHPMD => [
'title' => 'PHP Mess Detector',
'present' => function (): mixed {
return File::contains($this->dstDir . '/composer.json', 'phpmd/phpmd');
return File::contains($this->dstDir . '/composer.json', 'phpmd/phpmd') ||
File::exists($this->dstDir . '/phpmd.xml');
},
'composer.json' => function (JsonManipulator $cj): void {
$cj->removeSubNode('require-dev', 'phpmd/phpmd');
Expand All @@ -249,7 +251,8 @@ public static function getToolDefinitions(string $filter = 'all'): array {
self::PHPUNIT => [
'title' => 'PHPUnit',
'present' => function (): mixed {
return File::contains($this->dstDir . '/composer.json', 'phpunit/phpunit');
return File::contains($this->dstDir . '/composer.json', 'phpunit/phpunit') ||
File::exists($this->dstDir . '/phpunit.xml');
},
'composer.json' => function (JsonManipulator $cj): void {
$cj->removeSubNode('require-dev', 'phpunit/phpunit');
Expand Down Expand Up @@ -279,7 +282,8 @@ public static function getToolDefinitions(string $filter = 'all'): array {
'title' => 'Behat',
'present' => function (): mixed {
return File::contains($this->dstDir . '/composer.json', 'behat/behat') ||
File::contains($this->dstDir . '/composer.json', 'drupal/drupal-extension');
File::contains($this->dstDir . '/composer.json', 'drupal/drupal-extension') ||
File::exists($this->dstDir . '/behat.yml');
},
'composer.json' => function (JsonManipulator $cj): void {
$cj->removeSubNode('require-dev', 'behat/behat');
Expand Down
10 changes: 5 additions & 5 deletions .vortex/installer/src/Utils/Tui.php
Original file line number Diff line number Diff line change
Expand Up @@ -143,15 +143,15 @@ public static function list(array $values, ?string $title): void {
table($header, $rows);
}

public static function box(string $content, ?string $title = NULL, int $width = 80): void {
public static function box(string $content, ?string $title = NULL, ?int $width = NULL): void {
$rows = [];

$width = min($width, static::terminalWidth());
$width = $width ?? static::terminalWidth();

// 1 margin + 1 border + 1 padding + 1 padding + 1 border + 1 margin.
$offset = 6;

$content = wordwrap($content, $width - $offset, PHP_EOL, FALSE);
$content = wordwrap($content, $width - $offset, PHP_EOL, TRUE);

Comment on lines +146 to 155

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🛠️ Refactor suggestion

Clamp wrap width and guard against width ≤ offset

If $width is very small (or explicitly set below 6), wordwrap() can receive a non-positive width, which in PHP 8+ raises a ValueError. Also, when $width exceeds the actual terminal size, pre-wrapping to a too-large width causes unnecessary reflow later. Clamp to the effective terminal width and ensure a minimum of 1 column for wrapping. Apply the same wrap width to the title.

   public static function box(string $content, ?string $title = NULL, ?int $width = NULL): void {
     $rows = [];

-    $width = $width ?? static::terminalWidth();
+    $width = $width ?? static::terminalWidth();

     // 1 margin + 1 border + 1 padding + 1 padding + 1 border + 1 margin.
     $offset = 6;
-
-    $content = wordwrap($content, $width - $offset, PHP_EOL, TRUE);
+    // Use the smaller of requested width and actual terminal width; never below 1.
+    $wrapWidth = max(1, min($width, static::terminalWidth()) - $offset);
+    $content = wordwrap($content, $wrapWidth, PHP_EOL, TRUE);

     if ($title) {
-      $title = wordwrap($title, $width - $offset, PHP_EOL, FALSE);
+      $title = wordwrap($title, $wrapWidth, PHP_EOL, FALSE);
       $rows[] = [static::green($title)];
       $rows[] = [static::green(str_repeat('─', Strings::strlenPlain(explode(PHP_EOL, static::normalizeText($title))[0]))) . PHP_EOL];
     }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
public static function box(string $content, ?string $title = NULL, ?int $width = NULL): void {
$rows = [];
$width = min($width, static::terminalWidth());
$width = $width ?? static::terminalWidth();
// 1 margin + 1 border + 1 padding + 1 padding + 1 border + 1 margin.
$offset = 6;
$content = wordwrap($content, $width - $offset, PHP_EOL, FALSE);
$content = wordwrap($content, $width - $offset, PHP_EOL, TRUE);
public static function box(string $content, ?string $title = NULL, ?int $width = NULL): void {
$rows = [];
$width = $width ?? static::terminalWidth();
// 1 margin + 1 border + 1 padding + 1 padding + 1 border + 1 margin.
$offset = 6;
// Use the smaller of requested width and actual terminal width; never below 1.
$wrapWidth = max(1, min($width, static::terminalWidth()) - $offset);
$content = wordwrap($content, $wrapWidth, PHP_EOL, TRUE);
if ($title) {
$title = wordwrap($title, $wrapWidth, PHP_EOL, FALSE);
$rows[] = [static::green($title)];
$rows[] = [
static::green(
str_repeat(
'',
Strings::strlenPlain(
explode(PHP_EOL, static::normalizeText($title))[0]
)
)
) . PHP_EOL
];
}
// …rest of method…
}
🤖 Prompt for AI Agents
.vortex/installer/src/Utils/Tui.php around lines 146 to 155: the computed wrap
width passed to wordwrap can be non-positive or larger than the terminal, which
can throw a ValueError and cause unnecessary reflow; clamp $width to the
effective terminal width, compute $wrapWidth = max(1, min($width,
static::terminalWidth()) - $offset) and use that for wordwrap on both $content
and $title so you never pass a non-positive width and never wrap wider than the
terminal.

Comment on lines +154 to 155

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Consider grapheme-aware wrapping for Unicode

wordwrap() isn’t grapheme-aware and may split multi-byte characters in edge cases. If feasible, replace with a grapheme/column-aware wrapper (e.g., iterate over \X and accumulate using Strings::strlenPlain()), or add a TODO to revisit. Tests cover some Unicode, but not split boundaries.

🤖 Prompt for AI Agents
In .vortex/installer/src/Utils/Tui.php around lines 154-155, the current use of
wordwrap($content, $width - $offset, PHP_EOL, TRUE) is not grapheme-aware and
can split multi-byte Unicode graphemes; replace this call with a
grapheme/column-aware wrapper that iterates over Unicode grapheme clusters
(using PCRE \X or mbstring/grapheme functions) and accumulates clusters into
lines respecting display width (use Strings::strlenPlain() or equivalent to
measure column width) so breaks occur between clusters, or if full replacement
is out of scope, add a clear TODO comment here referencing the issue and add a
unit test that demonstrates a split boundary case to revisit later.

if ($title) {
$title = wordwrap($title, $width - $offset, PHP_EOL, FALSE);
Expand Down Expand Up @@ -193,8 +193,8 @@ public static function center(string $text, int $width = 80, ?string $border = N
return implode(PHP_EOL, $centered_lines);
}

public static function terminalWidth(): int {
return max(20, (new Terminal())->cols());
public static function terminalWidth(int $max = 100): int {
return min($max, max(20, (new Terminal())->cols()));
}

public static function normalizeText(string $text): string {
Expand Down
2 changes: 1 addition & 1 deletion .vortex/installer/tests/Fixtures/install/_baseline/.env
Original file line number Diff line number Diff line change
Expand Up @@ -189,7 +189,7 @@ VORTEX_NOTIFY_EMAIL_FROM=webmaster@star-wars.com
# Multiple names can be specified as a comma-separated list of email addresses
# with optional names in the format "email|name".
# Example: "to1@example.com|Jane Doe, to2@example.com|John Doe"
VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@star-wars.com
VORTEX_NOTIFY_EMAIL_RECIPIENTS="webmaster@star-wars.com|Webmaster"

################################################################################
# DEMO #
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
@@ -190,17 +185,3 @@
# with optional names in the format "email|name".
# Example: "to1@example.com|Jane Doe, to2@example.com|John Doe"
VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@star-wars.com
VORTEX_NOTIFY_EMAIL_RECIPIENTS="webmaster@star-wars.com|Webmaster"
-
-################################################################################
-# DEMO #
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
@@ -190,17 +189,3 @@
# with optional names in the format "email|name".
# Example: "to1@example.com|Jane Doe, to2@example.com|John Doe"
VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@star-wars.com
VORTEX_NOTIFY_EMAIL_RECIPIENTS="webmaster@star-wars.com|Webmaster"
-
-################################################################################
-# DEMO #
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -26,7 +26,7 @@
@@ -190,17 +196,3 @@
# with optional names in the format "email|name".
# Example: "to1@example.com|Jane Doe, to2@example.com|John Doe"
VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@star-wars.com
VORTEX_NOTIFY_EMAIL_RECIPIENTS="webmaster@star-wars.com|Webmaster"
-
-################################################################################
-# DEMO #
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -16,7 +16,7 @@
@@ -190,17 +185,3 @@
# with optional names in the format "email|name".
# Example: "to1@example.com|Jane Doe, to2@example.com|John Doe"
VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@star-wars.com
VORTEX_NOTIFY_EMAIL_RECIPIENTS="webmaster@star-wars.com|Webmaster"
-
-################################################################################
-# DEMO #
Expand Down
6 changes: 2 additions & 4 deletions .vortex/installer/tests/Fixtures/install/hosting_acquia/.env
Original file line number Diff line number Diff line change
Expand Up @@ -64,11 +64,10 @@

# Email address(es) to send notifications to.
#
@@ -189,18 +194,4 @@
# Multiple names can be specified as a comma-separated list of email addresses
@@ -190,17 +195,3 @@
# with optional names in the format "email|name".
# Example: "to1@example.com|Jane Doe, to2@example.com|John Doe"
-VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@star-wars.com
VORTEX_NOTIFY_EMAIL_RECIPIENTS="webmaster@star-wars.com|Webmaster"
-
-################################################################################
-# DEMO #
Expand All @@ -83,4 +82,3 @@
-
-# URL of the database used for demonstration with URL database download type.
-VORTEX_DB_DOWNLOAD_URL=https://github.com/drevops/vortex/releases/download/25.4.0/db_d11.demo.sql
+VORTEX_NOTIFY_EMAIL_RECIPIENTS=docrootmaster@star-wars.com
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
@@ -190,17 +197,3 @@
# with optional names in the format "email|name".
# Example: "to1@example.com|Jane Doe, to2@example.com|John Doe"
VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@star-wars.com
VORTEX_NOTIFY_EMAIL_RECIPIENTS="webmaster@star-wars.com|Webmaster"
-
-################################################################################
-# DEMO #
Expand Down
4 changes: 2 additions & 2 deletions .vortex/installer/tests/Fixtures/install/names/.env
Original file line number Diff line number Diff line change
Expand Up @@ -53,8 +53,8 @@
# Multiple names can be specified as a comma-separated list of email addresses
# with optional names in the format "email|name".
# Example: "to1@example.com|Jane Doe, to2@example.com|John Doe"
-VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@star-wars.com
+VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@death-star.com
-VORTEX_NOTIFY_EMAIL_RECIPIENTS="webmaster@star-wars.com|Webmaster"
+VORTEX_NOTIFY_EMAIL_RECIPIENTS="webmaster@death-star.com|Webmaster"

################################################################################
# DEMO #
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,7 @@
@@ -190,17 +197,3 @@
# with optional names in the format "email|name".
# Example: "to1@example.com|Jane Doe, to2@example.com|John Doe"
VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@star-wars.com
VORTEX_NOTIFY_EMAIL_RECIPIENTS="webmaster@star-wars.com|Webmaster"
-
-################################################################################
-# DEMO #
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@
@@ -190,17 +175,3 @@
# with optional names in the format "email|name".
# Example: "to1@example.com|Jane Doe, to2@example.com|John Doe"
VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@star-wars.com
VORTEX_NOTIFY_EMAIL_RECIPIENTS="webmaster@star-wars.com|Webmaster"
-
-################################################################################
-# DEMO #
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
@@ -190,17 +190,3 @@
# with optional names in the format "email|name".
# Example: "to1@example.com|Jane Doe, to2@example.com|John Doe"
VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@star-wars.com
VORTEX_NOTIFY_EMAIL_RECIPIENTS="webmaster@star-wars.com|Webmaster"
-
-################################################################################
-# DEMO #
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
@@ -190,17 +190,3 @@
# with optional names in the format "email|name".
# Example: "to1@example.com|Jane Doe, to2@example.com|John Doe"
VORTEX_NOTIFY_EMAIL_RECIPIENTS=webmaster@star-wars.com
VORTEX_NOTIFY_EMAIL_RECIPIENTS="webmaster@star-wars.com|Webmaster"
-
-################################################################################
-# DEMO #
Expand Down
Loading