Skip to content

Commit a3cd40a

Browse files
Merge branch '8.x'
2 parents d69e2e0 + e4ec76f commit a3cd40a

File tree

15 files changed

+280
-9
lines changed

15 files changed

+280
-9
lines changed
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
namespace Illuminate\Database;
4+
5+
use RuntimeException;
6+
7+
class ClassMorphViolationException extends RuntimeException
8+
{
9+
/**
10+
* The name of the affected Eloquent model.
11+
*
12+
* @var string
13+
*/
14+
public $model;
15+
16+
/**
17+
* Create a new exception instance.
18+
*
19+
* @param object $model
20+
*/
21+
public function __construct($model)
22+
{
23+
$class = get_class($model);
24+
25+
parent::__construct("No morph map defined for model [{$class}].");
26+
27+
$this->model = $class;
28+
}
29+
}

src/Illuminate/Database/Eloquent/Concerns/HasRelationships.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33
namespace Illuminate\Database\Eloquent\Concerns;
44

55
use Closure;
6+
use Illuminate\Database\ClassMorphViolationException;
67
use Illuminate\Database\Eloquent\Builder;
78
use Illuminate\Database\Eloquent\Collection;
89
use Illuminate\Database\Eloquent\Model;
@@ -731,6 +732,10 @@ public function getMorphClass()
731732
return array_search(static::class, $morphMap, true);
732733
}
733734

735+
if (Relation::requiresMorphMap()) {
736+
throw new ClassMorphViolationException($this);
737+
}
738+
734739
return static::class;
735740
}
736741

src/Illuminate/Database/Eloquent/Relations/Relation.php

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,13 @@ abstract class Relation implements BuilderContract
5656
*/
5757
public static $morphMap = [];
5858

59+
/**
60+
* Prevents morph relationships without a morph map.
61+
*
62+
* @var bool
63+
*/
64+
protected static $requireMorphMap = false;
65+
5966
/**
6067
* The count of self joins.
6168
*
@@ -387,6 +394,41 @@ protected function whereInMethod(Model $model, $key)
387394
: 'whereIn';
388395
}
389396

397+
/**
398+
* Prevent polymorphic relationships from being used without model mappings.
399+
*
400+
* @param bool $requireMorphMap
401+
* @return void
402+
*/
403+
public static function requireMorphMap($requireMorphMap = true)
404+
{
405+
static::$requireMorphMap = $requireMorphMap;
406+
}
407+
408+
/**
409+
* Determine if polymorphic relationships require explicit model mapping.
410+
*
411+
* @return bool
412+
*/
413+
public static function requiresMorphMap()
414+
{
415+
return static::$requireMorphMap;
416+
}
417+
418+
/**
419+
* Define the morph map for polymorphic relations and require all morphed models to be explicitly mapped.
420+
*
421+
* @param array|null $map
422+
* @param bool $merge
423+
* @return array
424+
*/
425+
public static function enforceMorphMap(array $map, $merge = true)
426+
{
427+
static::requireMorphMap();
428+
429+
return static::morphMap($map, $merge);
430+
}
431+
390432
/**
391433
* Set or get the morph map for polymorphic relations.
392434
*

src/Illuminate/Http/Client/PendingRequest.php

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -798,6 +798,28 @@ protected function populateResponse(Response $response)
798798
* @return \GuzzleHttp\Client
799799
*/
800800
public function buildClient()
801+
{
802+
return $this->requestsReusableClient()
803+
? $this->getReusableClient()
804+
: $this->createClient($this->buildHandlerStack());
805+
}
806+
807+
/**
808+
* Determine if a reusable client is required.
809+
*
810+
* @return bool
811+
*/
812+
protected function requestsReusableClient()
813+
{
814+
return ! is_null($this->client) || $this->async;
815+
}
816+
817+
/**
818+
* Retrieve a reusable Guzzle client.
819+
*
820+
* @return \GuzzleHttp\Client
821+
*/
822+
protected function getReusableClient()
801823
{
802824
return $this->client = $this->client ?: $this->createClient($this->buildHandlerStack());
803825
}

src/Illuminate/Http/Client/Request.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -120,9 +120,7 @@ public function header($key)
120120
*/
121121
public function headers()
122122
{
123-
return collect($this->request->getHeaders())->mapWithKeys(function ($values, $header) {
124-
return [$header => $values];
125-
})->all();
123+
return $this->request->getHeaders();
126124
}
127125

128126
/**

src/Illuminate/Http/Client/Response.php

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -107,9 +107,7 @@ public function header(string $header)
107107
*/
108108
public function headers()
109109
{
110-
return collect($this->response->getHeaders())->mapWithKeys(function ($v, $k) {
111-
return [$k => $v];
112-
})->all();
110+
return $this->response->getHeaders();
113111
}
114112

115113
/**

src/Illuminate/Support/Facades/View.php

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,7 @@
66
* @method static \Illuminate\Contracts\View\Factory addNamespace(string $namespace, string|array $hints)
77
* @method static \Illuminate\Contracts\View\View first(array $views, \Illuminate\Contracts\Support\Arrayable|array $data = [], array $mergeData = [])
88
* @method static \Illuminate\Contracts\View\Factory replaceNamespace(string $namespace, string|array $hints)
9+
* @method static \Illuminate\Contracts\View\Factory addExtension(string $extension, string $engine, \Closure|null $resolver = null)
910
* @method static \Illuminate\Contracts\View\View file(string $path, array $data = [], array $mergeData = [])
1011
* @method static \Illuminate\Contracts\View\View make(string $view, array $data = [], array $mergeData = [])
1112
* @method static array composer(array|string $views, \Closure|string $callback)

src/Illuminate/Support/ValidatedInput.php

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -68,6 +68,17 @@ public function except($keys)
6868
return $results;
6969
}
7070

71+
/**
72+
* Merge the validated input with the given array of additional data.
73+
*
74+
* @param array $items
75+
* @return static
76+
*/
77+
public function merge(array $items)
78+
{
79+
return new static(array_merge($this->input, $items));
80+
}
81+
7182
/**
7283
* Get the input as a collection.
7384
*

src/Illuminate/Testing/AssertableJsonString.php

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -96,7 +96,10 @@ public function assertExact(array $data)
9696

9797
$expected = $this->reorderAssocKeys($data);
9898

99-
PHPUnit::assertEquals(json_encode($expected), json_encode($actual));
99+
PHPUnit::assertEquals(
100+
json_encode($expected, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES),
101+
json_encode($actual, JSON_PRETTY_PRINT | JSON_UNESCAPED_SLASHES)
102+
);
100103

101104
return $this;
102105
}

src/Illuminate/Testing/Fluent/AssertableJson.php

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -117,6 +117,32 @@ public function first(Closure $callback): self
117117
return $this->scope($key, $callback);
118118
}
119119

120+
/**
121+
* Instantiate a new "scope" on each child element.
122+
*
123+
* @param \Closure $callback
124+
* @return $this
125+
*/
126+
public function each(Closure $callback): self
127+
{
128+
$props = $this->prop();
129+
130+
$path = $this->dotPath();
131+
132+
PHPUnit::assertNotEmpty($props, $path === ''
133+
? 'Cannot scope directly onto each element of the root level because it is empty.'
134+
: sprintf('Cannot scope directly onto each element of property [%s] because it is empty.', $path)
135+
);
136+
137+
foreach (array_keys($props) as $key) {
138+
$this->interactsWith($key);
139+
140+
$this->scope($key, $callback);
141+
}
142+
143+
return $this;
144+
}
145+
120146
/**
121147
* Create a new instance from an array.
122148
*

0 commit comments

Comments
 (0)