Skip to content

Commit

Permalink
Merge branch '8.x'
Browse files Browse the repository at this point in the history
  • Loading branch information
GrahamCampbell committed Jan 28, 2021
2 parents 71d8258 + 6bc7d1b commit a42a09c
Show file tree
Hide file tree
Showing 13 changed files with 162 additions and 18 deletions.
17 changes: 14 additions & 3 deletions src/Illuminate/Database/Eloquent/Concerns/HasAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -779,10 +779,14 @@ public function fillJsonAttribute($key, $value)
{
[$key, $path] = explode('->', $key, 2);

$this->attributes[$key] = $this->asJson($this->getArrayAttributeWithValue(
$value = $this->asJson($this->getArrayAttributeWithValue(
$path, $key, $value
));

$this->attributes[$key] = $this->isEncryptedCastable($key)
? $this->castAttributeAsEncryptedString($key, $value)
: $value;

return $this;
}

Expand Down Expand Up @@ -844,8 +848,15 @@ protected function getArrayAttributeWithValue($path, $key, $value)
*/
protected function getArrayAttributeByKey($key)
{
return isset($this->attributes[$key]) ?
$this->fromJson($this->attributes[$key]) : [];
if (! isset($this->attributes[$key])) {
return [];
}

return $this->fromJson(
$this->isEncryptedCastable($key)
? $this->fromEncryptedString($this->attributes[$key])
: $this->attributes[$key]
);
}

/**
Expand Down
10 changes: 3 additions & 7 deletions src/Illuminate/Database/Schema/PostgresSchemaState.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,16 +16,12 @@ class PostgresSchemaState extends SchemaState
*/
public function dump(Connection $connection, $path)
{
$searchPath = $connection->getConfig('search_path') ?: 'public';

$searchPath = $searchPath === 'public' ? '' : $searchPath.'.';

$excludedTables = collect($connection->getSchemaBuilder()->getAllTables())
->map->tablename
->reject(function ($table) {
return $table === $this->migrationTable;
})->map(function ($table) use ($searchPath) {
return '--exclude-table-data='.$searchPath.$table;
})->map(function ($table) {
return '--exclude-table-data="*.'.$table.'"';
})->implode(' ');

$this->makeProcess(
Expand All @@ -43,7 +39,7 @@ public function dump(Connection $connection, $path)
*/
public function load($path)
{
$command = 'PGPASSWORD=$LARAVEL_LOAD_PASSWORD pg_restore --no-owner --no-acl --host=$LARAVEL_LOAD_HOST --port=$LARAVEL_LOAD_PORT --username=$LARAVEL_LOAD_USER --dbname=$LARAVEL_LOAD_DATABASE $LARAVEL_LOAD_PATH';
$command = 'PGPASSWORD=$LARAVEL_LOAD_PASSWORD pg_restore --no-owner --no-acl --clean --if-exists --host=$LARAVEL_LOAD_HOST --port=$LARAVEL_LOAD_PORT --username=$LARAVEL_LOAD_USER --dbname=$LARAVEL_LOAD_DATABASE $LARAVEL_LOAD_PATH';

if (Str::endsWith($path, '.sql')) {
$command = 'PGPASSWORD=$LARAVEL_LOAD_PASSWORD psql --file=$LARAVEL_LOAD_PATH --host=$LARAVEL_LOAD_HOST --port=$LARAVEL_LOAD_PORT --username=$LARAVEL_LOAD_USER --dbname=$LARAVEL_LOAD_DATABASE';
Expand Down
32 changes: 31 additions & 1 deletion src/Illuminate/Foundation/Application.php
Original file line number Diff line number Diff line change
Expand Up @@ -112,6 +112,13 @@ class Application extends Container implements ApplicationContract, CachesConfig
*/
protected $databasePath;

/**
* The custom language file path defined by the developer.
*
* @var string
*/
protected $langPath;

/**
* The custom storage path defined by the developer.
*
Expand Down Expand Up @@ -407,7 +414,30 @@ public function useDatabasePath($path)
*/
public function langPath()
{
return $this->resourcePath().DIRECTORY_SEPARATOR.'lang';
if ($this->langPath) {
return $this->langPath;
}

if (is_dir($path = $this->resourcePath().DIRECTORY_SEPARATOR.'lang')) {
return $path;
}

return $this->basePath().DIRECTORY_SEPARATOR.'lang';
}

/**
* Set the language file directory.
*
* @param string $path
* @return $this
*/
public function useLangPath($path)
{
$this->langPath = $path;

$this->instance('path.lang', $path);

return $this;
}

/**
Expand Down
2 changes: 1 addition & 1 deletion src/Illuminate/Pagination/AbstractPaginator.php
Original file line number Diff line number Diff line change
Expand Up @@ -494,7 +494,7 @@ public static function currentPathResolver(Closure $resolver)
public static function resolveCurrentPage($pageName = 'page', $default = 1)
{
if (isset(static::$currentPageResolver)) {
return call_user_func(static::$currentPageResolver, $pageName);
return (int) call_user_func(static::$currentPageResolver, $pageName);
}

return $default;
Expand Down
13 changes: 11 additions & 2 deletions src/Illuminate/Routing/Middleware/SubstituteBindings.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Closure;
use Illuminate\Contracts\Routing\Registrar;
use Illuminate\Database\Eloquent\ModelNotFoundException;

class SubstituteBindings
{
Expand Down Expand Up @@ -34,9 +35,17 @@ public function __construct(Registrar $router)
*/
public function handle($request, Closure $next)
{
$this->router->substituteBindings($route = $request->route());
try {
$this->router->substituteBindings($route = $request->route());

$this->router->substituteImplicitBindings($route);
$this->router->substituteImplicitBindings($route);
} catch (ModelNotFoundException $exception) {
if ($route->getMissing()) {
return $route->getMissing()($request);
}

throw $exception;
}

return $next($request);
}
Expand Down
32 changes: 31 additions & 1 deletion src/Illuminate/Routing/Route.php
Original file line number Diff line number Diff line change
Expand Up @@ -933,6 +933,34 @@ public function setAction(array $action)
return $this;
}

/**
* Get the value of the action that should be taken on a missing model exception.
*
* @return \Closure|null
*/
public function getMissing()
{
$missing = $this->action['missing'] ?? null;

return is_string($missing) &&
Str::startsWith($missing, 'C:32:"Opis\\Closure\\SerializableClosure')
? unserialize($missing)
: $missing;
}

/**
* Define the callable that should be invoked on a missing model exception.
*
* @param \Closure $missing
* @return $this
*/
public function missing($missing)
{
$this->action['missing'] = $missing;

return $this;
}

/**
* Get all middleware, including the ones from the controller.
*
Expand Down Expand Up @@ -1167,8 +1195,10 @@ public function prepareForSerialization()
{
if ($this->action['uses'] instanceof Closure) {
$this->action['uses'] = serialize(new SerializableClosure($this->action['uses']));
}

// throw new LogicException("Unable to prepare route [{$this->uri}] for serialization. Uses Closure.");
if (isset($this->action['missing']) && $this->action['missing'] instanceof Closure) {
$this->action['missing'] = serialize(new SerializableClosure($this->action['missing']));
}

$this->compileRoute();
Expand Down
3 changes: 3 additions & 0 deletions src/Illuminate/Routing/Router.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
use Illuminate\Routing\Events\RouteMatched;
use Illuminate\Support\Collection;
use Illuminate\Support\Str;
use Illuminate\Support\Stringable;
use Illuminate\Support\Traits\Macroable;
use JsonSerializable;
use Psr\Http\Message\ResponseInterface as PsrResponseInterface;
Expand Down Expand Up @@ -769,6 +770,8 @@ public static function toResponse($request, $response)
$response = (new HttpFoundationFactory)->createResponse($response);
} elseif ($response instanceof Model && $response->wasRecentlyCreated) {
$response = new JsonResponse($response, 201);
} elseif ($response instanceof Stringable) {
$response = new Response($response->__toString(), 200, ['Content-Type' => 'text/html']);
} elseif (! $response instanceof SymfonyResponse &&
($response instanceof Arrayable ||
$response instanceof Jsonable ||
Expand Down
2 changes: 1 addition & 1 deletion src/Illuminate/Support/Stringable.php
Original file line number Diff line number Diff line change
Expand Up @@ -736,7 +736,7 @@ public function dd()
}

/**
* Convert the object into something JSON serializable.
* Convert the object to a string when JSON encoded.
*
* @return string
*/
Expand Down
6 changes: 5 additions & 1 deletion src/Illuminate/View/Compilers/ComponentTagCompiler.php
Original file line number Diff line number Diff line change
Expand Up @@ -463,6 +463,10 @@ protected function getAttributesFromAttributeString(string $attributeString)
$value = "'".$this->compileAttributeEchos($value)."'";
}

if (Str::startsWith($attribute, '::')) {
$attribute = substr($attribute, 1);
}

return [$attribute => $value];
})->toArray();
}
Expand Down Expand Up @@ -493,7 +497,7 @@ protected function parseBindAttributes(string $attributeString)
{
$pattern = "/
(?:^|\s+) # start of the string or whitespace between attributes
: # attribute needs to start with a semicolon
:(?!:) # attribute needs to start with a single colon
([\w\-:.@]+) # match the actual attribute name
= # only match attributes that have a value
/xm";
Expand Down
30 changes: 30 additions & 0 deletions tests/Integration/Database/EloquentModelEncryptedCastingTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -98,6 +98,36 @@ public function testJsonIsCastable()
]);
}

public function testJsonAttributeIsCastable()
{
$this->encrypter->expects('encrypt')
->with('{"key1":"value1"}', false)
->andReturn('encrypted-secret-json-string');
$this->encrypter->expects('decrypt')
->with('encrypted-secret-json-string', false)
->andReturn('{"key1":"value1"}');
$this->encrypter->expects('encrypt')
->with('{"key1":"value1","key2":"value2"}', false)
->andReturn('encrypted-secret-json-string2');
$this->encrypter->expects('decrypt')
->with('encrypted-secret-json-string2', false)
->andReturn('{"key1":"value1","key2":"value2"}');

$subject = new EncryptedCast([
'secret_json' => ['key1' => 'value1'],
]);
$subject->fill([
'secret_json->key2' => 'value2',
]);
$subject->save();

$this->assertSame(['key1' => 'value1', 'key2' => 'value2'], $subject->secret_json);
$this->assertDatabaseHas('encrypted_casts', [
'id' => $subject->id,
'secret_json' => 'encrypted-secret-json-string2',
]);
}

public function testObjectIsCastable()
{
$object = new \stdClass();
Expand Down
22 changes: 22 additions & 0 deletions tests/Routing/RoutingRouteTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
use Illuminate\Events\Dispatcher;
use Illuminate\Http\Exceptions\HttpResponseException;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Routing\Controller;
Expand Down Expand Up @@ -1671,6 +1672,27 @@ public function testImplicitBindingsWithOptionalParameterWithExistingKeyInUri()
$this->assertSame('taylor', $router->dispatch(Request::create('foo/taylor', 'GET'))->getContent());
}

public function testImplicitBindingsWithMissingModelHandledByMissing()
{
$router = $this->getRouter();
$router->get('foo/{bar}', [
'middleware' => SubstituteBindings::class,
'uses' => function (RouteModelBindingNullStub $bar = null) {
$this->assertInstanceOf(RouteModelBindingNullStub::class, $bar);

return $bar->first();
},
])->missing(function () {
return new RedirectResponse('/', 302);
});

$request = Request::create('foo/taylor', 'GET');

$response = $router->dispatch($request);
$this->assertTrue($response->isRedirect('/'));
$this->assertEquals(302, $response->getStatusCode());
}

public function testImplicitBindingsWithOptionalParameterWithNoKeyInUri()
{
$router = $this->getRouter();
Expand Down
3 changes: 2 additions & 1 deletion tests/Support/SupportStringableTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -546,8 +546,9 @@ public function testChunk()
$this->assertSame(['foo', 'bar', 'baz'], $chunks->all());
}

public function testJsonSerializable()
public function testJsonSerialize()
{
$this->assertSame('"foo"', json_encode($this->stringable('foo')));
$this->assertSame('"laravel-php-framework"', json_encode($this->stringable('LaravelPhpFramework')->kebab()));
$this->assertSame('["laravel-php-framework"]', json_encode([$this->stringable('LaravelPhpFramework')->kebab()]));
$this->assertSame('{"title":"laravel-php-framework"}', json_encode(['title' => $this->stringable('LaravelPhpFramework')->kebab()]));
Expand Down
8 changes: 8 additions & 0 deletions tests/View/Blade/BladeComponentTagCompilerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -88,6 +88,14 @@ public function testColonData()
<?php \$component->withAttributes([]); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
}

public function testEscapedColonAttribute()
{
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('<x-profile :user-id="1" ::title="user.name"></x-profile>');

$this->assertSame("##BEGIN-COMPONENT-CLASS##@component('Illuminate\Tests\View\Blade\TestProfileComponent', 'profile', ['userId' => 1])
<?php \$component->withAttributes([':title' => 'user.name']); ?> @endComponentClass##END-COMPONENT-CLASS##", trim($result));
}

public function testColonAttributesIsEscapedIfStrings()
{
$result = $this->compiler(['profile' => TestProfileComponent::class])->compileTags('<x-profile :src="\'foo\'"></x-profile>');
Expand Down

0 comments on commit a42a09c

Please sign in to comment.