Skip to content

Commit

Permalink
Merge remote-tracking branch 'upstream/8.x' into 8.x
Browse files Browse the repository at this point in the history
  • Loading branch information
TBlindaruk committed Dec 14, 2021
2 parents decb0a7 + f1d8ed5 commit 087232e
Show file tree
Hide file tree
Showing 10 changed files with 148 additions and 54 deletions.
9 changes: 8 additions & 1 deletion CHANGELOG-6.x.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,13 @@
# Release Notes for 6.x

## [Unreleased](https://github.com/laravel/framework/compare/v6.20.41...6.x)
## [Unreleased](https://github.com/laravel/framework/compare/v6.20.42...6.x)


## [v6.20.42 (2021-12-07)](https://github.com/laravel/framework/compare/v6.20.41...v6.20.42)

### Fixed
- Fixed for dropping columns when using MSSQL as ([#39905](https://github.com/laravel/framework/pull/39905))
- Fixed parent call in View ([#39908](https://github.com/laravel/framework/pull/39908))


## [v6.20.41 (2021-11-23)](https://github.com/laravel/framework/compare/v6.20.40...v6.20.41)
Expand Down
14 changes: 4 additions & 10 deletions src/Illuminate/Cache/RedisTaggedCache.php
Original file line number Diff line number Diff line change
Expand Up @@ -178,19 +178,13 @@ protected function deleteKeysByReference($reference)
*/
protected function deleteValues($referenceKey)
{
$cursor = $defaultCursorValue = '0';
$values = array_unique($this->store->connection()->smembers($referenceKey));

do {
[$cursor, $valuesChunk] = $this->store->connection()->sscan(
$referenceKey, $cursor, ['MATCH' => '*', 'COUNT' => 1000]
);

$valuesChunk = array_unique($valuesChunk);

if (count($valuesChunk) > 0) {
if (count($values) > 0) {
foreach (array_chunk($values, 1000) as $valuesChunk) {
$this->store->connection()->del(...$valuesChunk);
}
} while ($cursor !== $defaultCursorValue);
}
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Illuminate/Console/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -117,7 +117,7 @@ public static function phpBinary()
*/
public static function artisanBinary()
{
return defined('ARTISAN_BINARY') ? ProcessUtils::escapeArgument(ARTISAN_BINARY) : 'artisan';
return ProcessUtils::escapeArgument(defined('ARTISAN_BINARY') ? ARTISAN_BINARY : 'artisan');
}

/**
Expand Down
4 changes: 2 additions & 2 deletions src/Illuminate/Foundation/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -33,7 +33,7 @@ class Application extends Container implements ApplicationContract, CachesConfig
*
* @var string
*/
const VERSION = '8.75.0';
const VERSION = '8.76.1';

/**
* The base path for the Laravel installation.
Expand Down Expand Up @@ -248,7 +248,7 @@ public function bootstrapWith(array $bootstrappers)
*/
public function afterLoadingEnvironment(Closure $callback)
{
return $this->afterBootstrapping(
$this->afterBootstrapping(
LoadEnvironmentVariables::class, $callback
);
}
Expand Down
53 changes: 28 additions & 25 deletions src/Illuminate/Validation/Rules/Password.php
Original file line number Diff line number Diff line change
Expand Up @@ -270,36 +270,39 @@ public function passes($attribute, $value)
{
$this->messages = [];

$validator = Validator::make($this->data, [
$attribute => 'string|min:'.$this->min,
], $this->validator->customMessages, $this->validator->customAttributes);
$validator = Validator::make(
$this->data,
[$attribute => 'string|min:'.$this->min],
$this->validator->customMessages,
$this->validator->customAttributes
)->after(function ($validator) use ($attribute, $value) {
if (! is_string($value)) {
return;
}

$value = (string) $value;

if ($this->mixedCase && ! preg_match('/(\p{Ll}+.*\p{Lu})|(\p{Lu}+.*\p{Ll})/u', $value)) {
$validator->errors()->add($attribute, 'The :attribute must contain at least one uppercase and one lowercase letter.');
}

if ($this->letters && ! preg_match('/\pL/u', $value)) {
$validator->errors()->add($attribute, 'The :attribute must contain at least one letter.');
}

if ($this->symbols && ! preg_match('/\p{Z}|\p{S}|\p{P}/u', $value)) {
$validator->errors()->add($attribute, 'The :attribute must contain at least one symbol.');
}

if ($this->numbers && ! preg_match('/\pN/u', $value)) {
$validator->errors()->add($attribute, 'The :attribute must contain at least one number.');
}
});

if ($validator->fails()) {
return $this->fail($validator->messages()->all());
}

$value = (string) $value;

if ($this->mixedCase && ! preg_match('/(\p{Ll}+.*\p{Lu})|(\p{Lu}+.*\p{Ll})/u', $value)) {
$this->fail('The :attribute must contain at least one uppercase and one lowercase letter.');
}

if ($this->letters && ! preg_match('/\pL/u', $value)) {
$this->fail('The :attribute must contain at least one letter.');
}

if ($this->symbols && ! preg_match('/\p{Z}|\p{S}|\p{P}/u', $value)) {
$this->fail('The :attribute must contain at least one symbol.');
}

if ($this->numbers && ! preg_match('/\pN/u', $value)) {
$this->fail('The :attribute must contain at least one number.');
}

if (! empty($this->messages)) {
return false;
}

if ($this->uncompromised && ! Container::getInstance()->make(UncompromisedVerifier::class)->verify([
'value' => $value,
'threshold' => $this->compromisedThreshold,
Expand Down
8 changes: 4 additions & 4 deletions tests/Cache/CacheTaggedCacheTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -267,16 +267,16 @@ public function testRedisCacheTagsCanBeFlushed()
$store->shouldReceive('connection')->andReturn($conn = m::mock(stdClass::class));

// Forever tag keys
$conn->shouldReceive('sscan')->once()->with('prefix:foo:forever_ref', '0', ['MATCH' => '*', 'COUNT' => 1000])->andReturn(['0', ['key1', 'key2']]);
$conn->shouldReceive('sscan')->once()->with('prefix:bar:forever_ref', '0', ['MATCH' => '*', 'COUNT' => 1000])->andReturn(['0', ['key3']]);
$conn->shouldReceive('smembers')->once()->with('prefix:foo:forever_ref')->andReturn(['key1', 'key2']);
$conn->shouldReceive('smembers')->once()->with('prefix:bar:forever_ref')->andReturn(['key3']);
$conn->shouldReceive('del')->once()->with('key1', 'key2');
$conn->shouldReceive('del')->once()->with('key3');
$conn->shouldReceive('del')->once()->with('prefix:foo:forever_ref');
$conn->shouldReceive('del')->once()->with('prefix:bar:forever_ref');

// Standard tag keys
$conn->shouldReceive('sscan')->once()->with('prefix:foo:standard_ref', '0', ['MATCH' => '*', 'COUNT' => 1000])->andReturn(['0', ['key4', 'key5']]);
$conn->shouldReceive('sscan')->once()->with('prefix:bar:standard_ref', '0', ['MATCH' => '*', 'COUNT' => 1000])->andReturn(['0', ['key6']]);
$conn->shouldReceive('smembers')->once()->with('prefix:foo:standard_ref')->andReturn(['key4', 'key5']);
$conn->shouldReceive('smembers')->once()->with('prefix:bar:standard_ref')->andReturn(['key6']);
$conn->shouldReceive('del')->once()->with('key4', 'key5');
$conn->shouldReceive('del')->once()->with('key6');
$conn->shouldReceive('del')->once()->with('prefix:foo:standard_ref');
Expand Down
10 changes: 6 additions & 4 deletions tests/Console/ConsoleEventSchedulerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -101,9 +101,10 @@ public function testCommandCreatesNewArtisanCommand()

$events = $schedule->events();
$binary = $escape.PHP_BINARY.$escape;
$this->assertEquals($binary.' artisan queue:listen', $events[0]->command);
$this->assertEquals($binary.' artisan queue:listen --tries=3', $events[1]->command);
$this->assertEquals($binary.' artisan queue:listen --tries=3', $events[2]->command);
$artisan = $escape.'artisan'.$escape;
$this->assertEquals($binary.' '.$artisan.' queue:listen', $events[0]->command);
$this->assertEquals($binary.' '.$artisan.' queue:listen --tries=3', $events[1]->command);
$this->assertEquals($binary.' '.$artisan.' queue:listen --tries=3', $events[2]->command);
}

public function testCreateNewArtisanCommandUsingCommandClass()
Expand All @@ -115,7 +116,8 @@ public function testCreateNewArtisanCommandUsingCommandClass()

$events = $schedule->events();
$binary = $escape.PHP_BINARY.$escape;
$this->assertEquals($binary.' artisan foo:bar --force', $events[0]->command);
$artisan = $escape.'artisan'.$escape;
$this->assertEquals($binary.' '.$artisan.' foo:bar --force', $events[0]->command);
}

public function testCallCreatesNewJobWithTimezone()
Expand Down
2 changes: 1 addition & 1 deletion tests/Console/Scheduling/EventTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public function testBuildCommandInBackgroundUsingUnix()

$scheduleId = '"framework'.DIRECTORY_SEPARATOR.'schedule-eeb46c93d45e928d62aaf684d727e213b7094822"';

$this->assertSame("(php -i > '/dev/null' 2>&1 ; '".PHP_BINARY."' artisan schedule:finish {$scheduleId} \"$?\") > '/dev/null' 2>&1 &", $event->buildCommand());
$this->assertSame("(php -i > '/dev/null' 2>&1 ; '".PHP_BINARY."' 'artisan' schedule:finish {$scheduleId} \"$?\") > '/dev/null' 2>&1 &", $event->buildCommand());
}

/**
Expand Down
82 changes: 78 additions & 4 deletions tests/Database/PruneCommandTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,14 +5,13 @@
use Illuminate\Container\Container;
use Illuminate\Contracts\Events\Dispatcher as DispatcherContract;
use Illuminate\Database\Capsule\Manager as DB;
use Illuminate\Database\ConnectionResolverInterface;
use Illuminate\Database\Console\PruneCommand;
use Illuminate\Database\Eloquent\MassPrunable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Prunable;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Database\Events\ModelsPruned;
use Illuminate\Events\Dispatcher;
use Mockery as m;
use PHPUnit\Framework\TestCase;
use Symfony\Component\Console\Input\ArrayInput;
use Symfony\Component\Console\Output\BufferedOutput;
Expand Down Expand Up @@ -53,6 +52,36 @@ public function testPrunableTestModelWithoutPrunableRecords()
EOF, str_replace("\r", '', $output->fetch()));
}

public function testPrunableSoftDeletedModelWithPrunableRecords()
{
$db = new DB;
$db->addConnection([
'driver' => 'sqlite',
'database' => ':memory:',
]);
$db->bootEloquent();
$db->setAsGlobal();
DB::connection('default')->getSchemaBuilder()->create('prunables', function ($table) {
$table->string('value')->nullable();
$table->datetime('deleted_at')->nullable();
});
DB::connection('default')->table('prunables')->insert([
['value' => 1, 'deleted_at' => null],
['value' => 2, 'deleted_at' => '2021-12-01 00:00:00'],
['value' => 3, 'deleted_at' => null],
['value' => 4, 'deleted_at' => '2021-12-02 00:00:00'],
]);

$output = $this->artisan(['--model' => PrunableTestSoftDeletedModelWithPrunableRecords::class]);

$this->assertEquals(<<<'EOF'
2 [Illuminate\Tests\Database\PrunableTestSoftDeletedModelWithPrunableRecords] records have been pruned.

EOF, str_replace("\r", '', $output->fetch()));

$this->assertEquals(2, PrunableTestSoftDeletedModelWithPrunableRecords::withTrashed()->count());
}

public function testNonPrunableTest()
{
$output = $this->artisan(['--model' => NonPrunableTestModel::class]);
Expand All @@ -70,6 +99,7 @@ public function testTheCommandMayBePretended()
'driver' => 'sqlite',
'database' => ':memory:',
]);
$db->bootEloquent();
$db->setAsGlobal();
DB::connection('default')->getSchemaBuilder()->create('prunables', function ($table) {
$table->string('name')->nullable();
Expand All @@ -82,8 +112,6 @@ public function testTheCommandMayBePretended()
['name' => 'stuart', 'value' => 4],
['name' => 'bello', 'value' => 5],
]);
$resolver = m::mock(ConnectionResolverInterface::class, ['connection' => $db->getConnection('default')]);
PrunableTestModelWithPrunableRecords::setConnectionResolver($resolver);

$output = $this->artisan([
'--model' => PrunableTestModelWithPrunableRecords::class,
Expand All @@ -98,6 +126,39 @@ public function testTheCommandMayBePretended()
$this->assertEquals(5, PrunableTestModelWithPrunableRecords::count());
}

public function testTheCommandMayBePretendedOnSoftDeletedModel()
{
$db = new DB;
$db->addConnection([
'driver' => 'sqlite',
'database' => ':memory:',
]);
$db->bootEloquent();
$db->setAsGlobal();
DB::connection('default')->getSchemaBuilder()->create('prunables', function ($table) {
$table->string('value')->nullable();
$table->datetime('deleted_at')->nullable();
});
DB::connection('default')->table('prunables')->insert([
['value' => 1, 'deleted_at' => null],
['value' => 2, 'deleted_at' => '2021-12-01 00:00:00'],
['value' => 3, 'deleted_at' => null],
['value' => 4, 'deleted_at' => '2021-12-02 00:00:00'],
]);

$output = $this->artisan([
'--model' => PrunableTestSoftDeletedModelWithPrunableRecords::class,
'--pretend' => true,
]);

$this->assertEquals(<<<'EOF'
2 [Illuminate\Tests\Database\PrunableTestSoftDeletedModelWithPrunableRecords] records will be pruned.

EOF, str_replace("\r", '', $output->fetch()));

$this->assertEquals(4, PrunableTestSoftDeletedModelWithPrunableRecords::withTrashed()->count());
}

protected function artisan($arguments)
{
$input = new ArrayInput($arguments);
Expand Down Expand Up @@ -139,6 +200,19 @@ public function prunable()
}
}

class PrunableTestSoftDeletedModelWithPrunableRecords extends Model
{
use MassPrunable, SoftDeletes;

protected $table = 'prunables';
protected $connection = 'default';

public function prunable()
{
return static::where('value', '>=', 3);
}
}

class PrunableTestModelWithoutPrunableRecords extends Model
{
use Prunable;
Expand Down
18 changes: 16 additions & 2 deletions tests/Validation/ValidationPasswordRuleTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -144,8 +144,15 @@ public function testMessagesOrder()
'validation.required',
]);

$this->fails($makeRules(), ['foo', 'azdazd', '1231231'], [
$this->fails($makeRules(), ['foo', 'azdazd'], [
'validation.min.string',
'The my password must contain at least one uppercase and one lowercase letter.',
'The my password must contain at least one number.',
]);

$this->fails($makeRules(), ['1231231'], [
'validation.min.string',
'The my password must contain at least one uppercase and one lowercase letter.',
]);

$this->fails($makeRules(), ['4564654564564'], [
Expand All @@ -165,8 +172,15 @@ public function testMessagesOrder()

$this->passes($makeRules(), [null]);

$this->fails($makeRules(), ['foo', 'azdazd', '1231231'], [
$this->fails($makeRules(), ['foo', 'azdazd'], [
'validation.min.string',
'The my password must contain at least one symbol.',
]);

$this->fails($makeRules(), ['1231231'], [
'validation.min.string',
'The my password must contain at least one letter.',
'The my password must contain at least one symbol.',
]);

$this->fails($makeRules(), ['aaaaaaaaa', 'TJQSJQSIUQHS'], [
Expand Down

0 comments on commit 087232e

Please sign in to comment.