diff --git a/config/sets/laravel-code-quality.php b/config/sets/laravel-code-quality.php
index b8644ff8..e8ba5935 100644
--- a/config/sets/laravel-code-quality.php
+++ b/config/sets/laravel-code-quality.php
@@ -4,8 +4,10 @@
use Rector\Config\RectorConfig;
use RectorLaravel\Rector\Assign\CallOnAppArrayAccessToStandaloneAssignRector;
+use RectorLaravel\Rector\MethodCall\ReverseConditionableMethodCallRector;
return static function (RectorConfig $rectorConfig): void {
$rectorConfig->import(__DIR__ . '/../config.php');
$rectorConfig->rule(CallOnAppArrayAccessToStandaloneAssignRector::class);
+ $rectorConfig->rule(ReverseConditionableMethodCallRector::class);
};
diff --git a/docs/rector_rules_overview.md b/docs/rector_rules_overview.md
index 16b4f746..530b51c4 100644
--- a/docs/rector_rules_overview.md
+++ b/docs/rector_rules_overview.md
@@ -1,4 +1,4 @@
-# 65 Rules Overview
+# 66 Rules Overview
## AbortIfRector
@@ -1231,6 +1231,26 @@ Change static `validate()` method to `$request->validate()`
+## ReverseConditionableMethodCallRector
+
+Reverse conditionable method calls
+
+- class: [`RectorLaravel\Rector\MethodCall\ReverseConditionableMethodCallRector`](../src/Rector/MethodCall/ReverseConditionableMethodCallRector.php)
+
+```diff
+-$conditionable->when(!$condition, function () {});
++$conditionable->unless($condition, function () {});
+```
+
+
+
+```diff
+-$conditionable->unless(!$condition, function () {});
++$conditionable->when($condition, function () {});
+```
+
+
+
## RouteActionCallableRector
Use PHP callable syntax instead of string syntax for controller route declarations.
diff --git a/src/Rector/MethodCall/ReverseConditionableMethodCallRector.php b/src/Rector/MethodCall/ReverseConditionableMethodCallRector.php
new file mode 100644
index 00000000..871cd125
--- /dev/null
+++ b/src/Rector/MethodCall/ReverseConditionableMethodCallRector.php
@@ -0,0 +1,88 @@
+when(!$condition, function () {});
+CODE_SAMPLE,
+ <<<'CODE_SAMPLE'
+$conditionable->unless($condition, function () {});
+CODE_SAMPLE
+ ),
+ new CodeSample(<<<'CODE_SAMPLE'
+$conditionable->unless(!$condition, function () {});
+CODE_SAMPLE,
+ <<<'CODE_SAMPLE'
+$conditionable->when($condition, function () {});
+CODE_SAMPLE
+ ),
+ ]
+ );
+ }
+
+ public function getNodeTypes(): array
+ {
+ return [MethodCall::class];
+ }
+
+ /**
+ * @param MethodCall $node
+ */
+ public function refactor(Node $node): ?MethodCall
+ {
+ if (! $this->isObjectType($node->var, new ObjectType(self::CONDITIONABLE_TRAIT))) {
+ return null;
+ }
+
+ if (! $this->isNames($node->name, ['when', 'unless'])) {
+ return null;
+ }
+
+ if ($node->isFirstClassCallable()) {
+ return null;
+ }
+
+ if ($node->getArgs() === []) {
+ return null;
+ }
+
+ $arg = $node->getArgs()[0];
+
+ if (! $node->name instanceof Identifier) {
+ return null;
+ }
+
+ if ($arg->value instanceof BooleanNot) {
+ $node->args[0] = new Arg($arg->value->expr);
+ $name = $node->name->toString() === 'when' ? 'unless' : 'when';
+
+ $node->name = new Identifier($name);
+
+ return $node;
+ }
+
+ return null;
+ }
+}
diff --git a/stubs/Illuminate/Support/Traits/Conditionable.php b/stubs/Illuminate/Support/Traits/Conditionable.php
new file mode 100644
index 00000000..58abe2cd
--- /dev/null
+++ b/stubs/Illuminate/Support/Traits/Conditionable.php
@@ -0,0 +1,18 @@
+when(!true, function () {});
+$conditionable->unless(!false, function () {});
+
+?>
+-----
+unless(true, function () {});
+$conditionable->when(false, function () {});
+
+?>
diff --git a/tests/Rector/MethodCall/ReverseConditionableMethodCallRector/Fixture/skip_non_conditionable_object.php.inc b/tests/Rector/MethodCall/ReverseConditionableMethodCallRector/Fixture/skip_non_conditionable_object.php.inc
new file mode 100644
index 00000000..3db99d0b
--- /dev/null
+++ b/tests/Rector/MethodCall/ReverseConditionableMethodCallRector/Fixture/skip_non_conditionable_object.php.inc
@@ -0,0 +1,10 @@
+when(!true, function () {});
+$conditionable->unless(!false, function () {});
+
+?>
diff --git a/tests/Rector/MethodCall/ReverseConditionableMethodCallRector/ReverseConditionableMethodCallRectorTest.php b/tests/Rector/MethodCall/ReverseConditionableMethodCallRector/ReverseConditionableMethodCallRectorTest.php
new file mode 100644
index 00000000..95715778
--- /dev/null
+++ b/tests/Rector/MethodCall/ReverseConditionableMethodCallRector/ReverseConditionableMethodCallRectorTest.php
@@ -0,0 +1,31 @@
+doTestFile($filePath);
+ }
+
+ public function provideConfigFilePath(): string
+ {
+ return __DIR__ . '/config/configured_rule.php';
+ }
+}
diff --git a/tests/Rector/MethodCall/ReverseConditionableMethodCallRector/Source/ConditionableExample.php b/tests/Rector/MethodCall/ReverseConditionableMethodCallRector/Source/ConditionableExample.php
new file mode 100644
index 00000000..25290570
--- /dev/null
+++ b/tests/Rector/MethodCall/ReverseConditionableMethodCallRector/Source/ConditionableExample.php
@@ -0,0 +1,10 @@
+import(__DIR__ . '/../../../../../config/config.php');
+
+ $rectorConfig->rule(ReverseConditionableMethodCallRector::class);
+};