Skip to content

Commit

Permalink
Merge pull request #622 from octobercms/next
Browse files Browse the repository at this point in the history
Backport features from next to develop
  • Loading branch information
daftspunk authored Jan 26, 2024
2 parents 387541e + d863b9a commit ab04bb2
Show file tree
Hide file tree
Showing 55 changed files with 1,369 additions and 623 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@
"composer/composer": "^2.0.0",
"doctrine/dbal": "^2.13.3|^3.1.4",
"linkorb/jsmin-php": "~1.0",
"wikimedia/less.php": "~3.0",
"wikimedia/less.php": "~4.1",
"scssphp/scssphp": "~1.0",
"symfony/yaml": "^6.0",
"twig/twig": "~3.0",
Expand Down
8 changes: 8 additions & 0 deletions helpers/Auth.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

/**
* Auth
*
* @see \Responsiv\User\Classes\AuthManager
*/
class Auth extends October\Rain\Support\Facades\Auth {}
8 changes: 8 additions & 0 deletions helpers/Currency.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
<?php

/**
* Currency
*
* @see \Responsiv\Shop\Classes\CurrencyManager
*/
class Currency extends October\Rain\Support\Facades\Currency {}
26 changes: 26 additions & 0 deletions src/Auth/Concerns/HasProviderProxy.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
<?php namespace October\Rain\Auth\Concerns;

/**
* HasProviderProxy provides proxy methods to emulate Laravel's auth provider
*
* @package october\auth
* @author Alexey Bobkov, Samuel Georges
*/
trait HasProviderProxy
{
/**
* getProvider just passes it back to the current class
*/
public function getProvider()
{
return $this;
}

/**
* getModel returns the class name for the user model
*/
public function getModel()
{
return $this->userModel;
}
}
1 change: 1 addition & 0 deletions src/Auth/Manager.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@ class Manager implements StatefulGuard
use \October\Rain\Auth\Concerns\HasThrottle;
use \October\Rain\Auth\Concerns\HasImpersonation;
use \October\Rain\Auth\Concerns\HasStatefulGuard;
use \October\Rain\Auth\Concerns\HasProviderProxy;
use \October\Rain\Auth\Concerns\HasGuard;

/**
Expand Down
4 changes: 2 additions & 2 deletions src/Auth/Models/User.php
Original file line number Diff line number Diff line change
Expand Up @@ -421,7 +421,7 @@ public function addGroup($group)
{
if (!$this->inGroup($group)) {
$this->groups()->attach($group);
$this->reloadRelations('groups');
$this->unsetRelation('groups');
}

return true;
Expand All @@ -436,7 +436,7 @@ public function removeGroup($group)
{
if ($this->inGroup($group)) {
$this->groups()->detach($group);
$this->reloadRelations('groups');
$this->unsetRelation('groups');
}

return true;
Expand Down
4 changes: 0 additions & 4 deletions src/Database/Attach/File.php
Original file line number Diff line number Diff line change
Expand Up @@ -517,10 +517,6 @@ public function beforeSave()
if ($this->data instanceof UploadedFile) {
$this->fromPost($this->data);
}
// @deprecated see AttachOneOrMany::isValidFileData
else {
$this->fromFile($this->data);
}

$this->data = null;
}
Expand Down
19 changes: 19 additions & 0 deletions src/Database/Builder.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
use Illuminate\Pagination\Paginator;
use Illuminate\Database\Eloquent\Builder as BuilderModel;
use October\Rain\Support\Facades\DbDongle;
use Closure;

/**
* Builder class for queries, extends the Eloquent builder class.
Expand All @@ -13,6 +14,24 @@
class Builder extends BuilderModel
{
use \October\Rain\Database\Concerns\HasNicerPagination;
use \October\Rain\Database\Concerns\HasEagerLoadAttachRelation;

/**
* eagerLoadRelation eagerly load the relationship on a set of models, with support
* for attach relations.
* @param array $models
* @param string $name
* @param \Closure $constraints
* @return array
*/
protected function eagerLoadRelation(array $models, $name, Closure $constraints)
{
if ($result = $this->eagerLoadAttachRelation($models, $name, $constraints)) {
return $result;
}

return parent::eagerLoadRelation($models, $name, $constraints);
}

/**
* lists gets an array with the values of a given column.
Expand Down
2 changes: 1 addition & 1 deletion src/Database/Concerns/HasAttributes.php
Original file line number Diff line number Diff line change
Expand Up @@ -164,7 +164,7 @@ public function setAttribute($key, $value)

// Handle direct relation setting
if ($this->hasRelation($key) && !$this->hasSetMutator($key)) {
return $this->setRelationValue($key, $value);
return $this->setRelationSimpleValue($key, $value);
}

/**
Expand Down
66 changes: 66 additions & 0 deletions src/Database/Concerns/HasEagerLoadAttachRelation.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php namespace October\Rain\Database\Concerns;

use Closure;

/**
* HasNicerPagination for a query builder
*/
trait HasEagerLoadAttachRelation
{
/**
* @var array eagerLoadAttachResultCache
*/
protected $eagerLoadAttachResultCache = [];

/**
* eagerLoadAttachRelation eagerly loads an attachment relationship on a set of models.
* @param string $relatedModel
* @param array $models
* @param string $name
* @param \Closure $constraints
* @return array|null
*/
protected function eagerLoadAttachRelation(array $models, $name, Closure $constraints)
{
// Look up relation type
$relationType = $this->getModel()->getRelationType($name);
if (!$relationType || !in_array($relationType, ['attachOne', 'attachMany'])) {
return null;
}

// Only vanilla attachments are supported, pass complex lookups back to Laravel
$definition = $this->getModel()->getRelationDefinition($name);
if (isset($definition['conditions']) || isset($definition['scope'])) {
return null;
}

// Opt-out of the combined eager loading logic
if (isset($definition['combineEager']) && $definition['combineEager'] === false) {
return null;
}

$relation = $this->getRelation($name);
$relatedModel = get_class($relation->getRelated());

// Perform a global look up attachment without the 'field' constraint
// to produce a combined subset of all possible attachment relations.
if (!isset($this->eagerLoadAttachResultCache[$relatedModel])) {
$relation->addCommonEagerConstraints($models);

// Note this takes first constraint only. If it becomes a problem one solution
// could be to compare the md5 of toSql() to ensure uniqueness. The workaround
// for this edge case is to set combineEager => false in the definition.
$constraints($relation);

$this->eagerLoadAttachResultCache[$relatedModel] = $relation->getEager();
}

$results = $this->eagerLoadAttachResultCache[$relatedModel];

return $relation->match(
$relation->initRelation($models, $name),
$results->where('field', $name),
$name
);
}
}
24 changes: 14 additions & 10 deletions src/Database/Concerns/HasEvents.php
Original file line number Diff line number Diff line change
Expand Up @@ -18,9 +18,7 @@ trait HasEvents
*/
protected function bootNicerEvents()
{
$class = get_called_class();

if (isset(static::$eventsBooted[$class])) {
if (isset(static::$eventsBooted[static::class])) {
return;
}

Expand All @@ -39,20 +37,26 @@ protected function bootNicerEvents()
];

foreach ($nicerEvents as $eventMethod => $method) {
self::$eventMethod(function ($model) use ($method) {
$model->fireEvent('model.' . $method);

if ($model->methodExists($method)) {
return $model->$method();
}
self::registerModelEvent($eventMethod, function ($model) use ($method) {
$model->fireEvent("model.{$method}");
return $model->$method();
});
}

// Hooks for late stage attribute changes
self::registerModelEvent('creating', function ($model) {
$model->fireEvent('model.beforeSaveDone');
});

self::registerModelEvent('updating', function ($model) {
$model->fireEvent('model.beforeSaveDone');
});

// Boot event
$this->fireEvent('model.afterBoot');
$this->afterBoot();

static::$eventsBooted[$class] = true;
static::$eventsBooted[static::class] = true;
}

/**
Expand Down
34 changes: 23 additions & 11 deletions src/Database/Concerns/HasRelationships.php
Original file line number Diff line number Diff line change
Expand Up @@ -254,12 +254,24 @@ public function isRelationTypeSingular($name): bool
}

/**
* makeRelation returns a relation class object
* @param string $name Relation name
* @return object
* makeRelation returns a relation class object, supporting nested relations with
* dot notation
* @param string $name
* @return \Model|null
*/
public function makeRelation($name)
{
if (str_contains($name, '.')) {
$model = $this;
$parts = explode('.', $name);
while ($relationName = array_shift($parts)) {
if (!$model = $model->makeRelation($relationName)) {
return null;
}
}
return $model;
}

$relation = $this->getRelationDefinition($name);
$relationType = $this->getRelationType($name);

Expand Down Expand Up @@ -330,15 +342,15 @@ protected function handleRelation($relationName)
throw new InvalidArgumentException(sprintf(
"Relation '%s' on model '%s' should have at least a classname.",
$relationName,
get_called_class()
static::class
));
}

if (isset($relation[0]) && $relationType === 'morphTo') {
throw new InvalidArgumentException(sprintf(
"Relation '%s' on model '%s' is a morphTo relation and should not contain additional arguments.",
$relationName,
get_called_class()
static::class
));
}

Expand Down Expand Up @@ -393,7 +405,7 @@ protected function handleRelation($relationName)
break;

default:
throw new InvalidArgumentException(sprintf("There is no such relation type known as '%s' on model '%s'.", $relationType, get_called_class()));
throw new InvalidArgumentException(sprintf("There is no such relation type known as '%s' on model '%s'.", $relationType, static::class));
}

// Relation hook event
Expand Down Expand Up @@ -430,7 +442,7 @@ protected function validateRelationArgs($relationName, $optional, $required = []
throw new InvalidArgumentException(sprintf(
'Relation "%s" on model "%s" should contain the following key(s): %s',
$relationName,
get_called_class(),
static::class,
implode(', ', $missingRequired)
));
}
Expand Down Expand Up @@ -848,17 +860,17 @@ protected function getRelationCaller()
}

/**
* getRelationValue returns a relation key value(s), not as an object.
* getRelationSimpleValue returns a relation key value(s), not as an object.
*/
public function getRelationValue($relationName)
public function getRelationSimpleValue($relationName)
{
return $this->$relationName()->getSimpleValue();
}

/**
* setRelationValue sets a relation value directly from its attribute.
* setRelationSimpleValue sets a relation value directly from its attribute.
*/
protected function setRelationValue($relationName, $value)
protected function setRelationSimpleValue($relationName, $value)
{
$this->$relationName()->setSimpleValue($value);
}
Expand Down
8 changes: 4 additions & 4 deletions src/Database/ExpandoModel.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,13 +31,13 @@ public function __construct(array $attributes = [])
$this->bindEvent('model.afterSave', [$this, 'expandoAfterSave']);

// Process attributes last for traits with attribute modifiers
$this->bindEvent('model.saveInternal', [$this, 'expandoSaveInternal'], -1);
$this->bindEvent('model.beforeSaveDone', [$this, 'expandoBeforeSaveDone'], -1);

$this->addJsonable($this->expandoColumn);
}

/**
* afterModelFetch constructor event
* expandoAfterFetch constructor event
*/
public function expandoAfterFetch()
{
Expand All @@ -47,9 +47,9 @@ public function expandoAfterFetch()
}

/**
* saveModelInternal constructor event
* expandoBeforeSaveDone constructor event
*/
public function expandoSaveInternal()
public function expandoBeforeSaveDone()
{
$this->{$this->expandoColumn} = array_diff_key(
$this->attributes,
Expand Down
15 changes: 3 additions & 12 deletions src/Database/Model.php
Original file line number Diff line number Diff line change
Expand Up @@ -110,17 +110,15 @@ public function reload()
}

/**
* reloadRelations for this model.
* @param string $relationName
* @return void
* @deprecated use unsetRelation or unsetRelations
*/
public function reloadRelations($relationName = null)
{
if (!$relationName) {
$this->setRelations([]);
$this->unsetRelations();
}
else {
unset($this->relations[$relationName]);
$this->unsetRelation($relationName);
}
}

Expand Down Expand Up @@ -376,13 +374,6 @@ protected function saveInternal($options = [])
return false;
}

// Validate attributes before trying to save
foreach ($this->attributes as $attribute => $value) {
if (is_array($value)) {
throw new Exception(sprintf('Unexpected type of array when attempting to save attribute "%s", try adding it to the $jsonable property.', $attribute));
}
}

// Apply pre deferred bindings
if ($this->sessionKey !== null) {
$this->commitDeferredBefore($this->sessionKey);
Expand Down
Loading

0 comments on commit ab04bb2

Please sign in to comment.