Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Editing nested elements when owner is new for site (and still a provisional draft) #15898

Merged
merged 8 commits into from
Oct 17, 2024
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,9 @@

## Unreleased

- Added `craft\elements\db\NestedElementQueryInterface`.
- Fixed a bug where uninstalled/missing plugins weren’t getting status indicators on the Plugins index page.
- Fixed errors that occurred when working with nested entries for a newly-added site. ([#15898](https://github.com/craftcms/cms/pull/15898))

## 5.4.8 - 2024-10-15

Expand Down
29 changes: 18 additions & 11 deletions src/base/Element.php
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,7 @@
use craft\elements\db\EagerLoadPlan;
use craft\elements\db\ElementQuery;
use craft\elements\db\ElementQueryInterface;
use craft\elements\db\NestedElementQueryInterface;
use craft\elements\ElementCollection;
use craft\elements\exporters\Expanded;
use craft\elements\exporters\Raw;
Expand Down Expand Up @@ -2881,16 +2882,21 @@ public function getCanonical(bool $anySite = false): ElementInterface
$prop = $anySite ? '_canonicalAnySite' : '_canonical';

if (!isset($this->$prop)) {
$this->$prop = static::find()
->id($this->_canonicalId)
->siteId($anySite ? '*' : $this->siteId)
->preferSites([$this->siteId])
->structureId($this->structureId)
->unique()
->status(null)
->trashed(null)
->ignorePlaceholders()
->one() ?? false;
$query = static::find()
->id($this->_canonicalId)
->siteId($anySite ? '*' : $this->siteId)
->preferSites([$this->siteId])
->structureId($this->structureId)
->unique()
->status(null)
->trashed(null)
->ignorePlaceholders();

if ($this instanceof NestedElementInterface && $query instanceof NestedElementQueryInterface) {
$query->ownerId($this->getOwnerId());
}

$this->$prop = $query->one();
}

return $this->$prop ?: $this;
Expand Down Expand Up @@ -3205,7 +3211,7 @@ public function getLink(): ?Markup
public function getCrumbs(): array
{
if ($this instanceof NestedElementInterface) {
$owner = $this->getPrimaryOwner();
$owner = $this->getOwner();
if ($owner) {
return [
...$owner->getCrumbs(),
Expand Down Expand Up @@ -3626,6 +3632,7 @@ protected function safeActionMenuItems(): array
'draftId' => $this->isProvisionalDraft ? null : $this->draftId,
'revisionId' => $this->revisionId,
'siteId' => $this->siteId,
'ownerId' => $this instanceof NestedElementInterface ? $this->getOwnerId() : null,
],
]);
}
Expand Down
13 changes: 10 additions & 3 deletions src/controllers/AppController.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use craft\base\ElementInterface;
use craft\base\Iconic;
use craft\base\UtilityInterface;
use craft\elements\db\NestedElementQueryInterface;
use craft\enums\CmsEdition;
use craft\enums\LicenseKeyStatus;
use craft\errors\BusyResourceException;
Expand Down Expand Up @@ -761,21 +762,27 @@ public function actionRenderElements(): Response
/** @var string|ElementInterface $elementType */
$elementType = $criterion['type'];
$id = $criterion['id'];
$ownerId = $criterion['ownerId'] ?? null;
$siteId = $criterion['siteId'];
$instances = $criterion['instances'];

if (!$id || (!is_numeric($id) && !(is_array($id) && ArrayHelper::isNumeric($id)))) {
throw new BadRequestHttpException('Invalid element ID');
}

$elements = $elementType::find()
$query = $elementType::find()
->id($id)
->fixedOrder()
->drafts(null)
->revisions(null)
->siteId($siteId)
->status(null)
->all();
->status(null);

if ($query instanceof NestedElementQueryInterface) {
$query->ownerId($ownerId);
}

$elements = $query->all();

// See if there are any provisional drafts we should swap these out with
ElementHelper::swapInProvisionalDrafts($elements);
Expand Down
25 changes: 20 additions & 5 deletions src/controllers/ElementsController.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@
use craft\base\NestedElementInterface;
use craft\behaviors\DraftBehavior;
use craft\behaviors\RevisionBehavior;
use craft\elements\db\ElementQueryInterface;
use craft\elements\db\NestedElementQueryInterface;
use craft\elements\User;
use craft\enums\MenuItemType;
use craft\errors\InvalidElementException;
Expand Down Expand Up @@ -72,6 +74,7 @@ class ElementsController extends Controller
private ?string $_elementUid = null;
private ?int $_draftId = null;
private ?int $_revisionId = null;
private ?int $_ownerId = null;
private ?int $_siteId = null;

private ?bool $_enabled = null;
Expand Down Expand Up @@ -113,6 +116,7 @@ public function beforeAction($action): bool
$this->_elementUid = $this->_param('elementUid');
$this->_draftId = $this->_param('draftId');
$this->_revisionId = $this->_param('revisionId');
$this->_ownerId = $this->_param('ownerId');
$this->_siteId = $this->_param('siteId');
$this->_enabled = $this->_param('enabled', $this->_param('setEnabled', true) ? true : null);
$this->_enabledForSite = $this->_param('enabledForSite');
Expand Down Expand Up @@ -427,6 +431,7 @@ public function actionEdit(?ElementInterface $element, ?int $elementId = null):
'previewToken' => $previewTargets ? $security->generateRandomString() : null,
'previewParamValue' => $previewTargets ? $security->hashData(StringHelper::randomString(10)) : null,
'revisionId' => $element->revisionId,
'ownerId' => $element instanceof NestedElementInterface ? $element->getOwnerId() : null,
'siteId' => $element->siteId,
'siteStatuses' => $siteStatuses,
'siteToken' => (!Craft::$app->getIsLive() || !$element->getSite()->enabled) ? $security->hashData((string)$element->siteId) : null,
Expand Down Expand Up @@ -2105,7 +2110,7 @@ private function _element(

// Loading an existing element?
if ($this->_draftId || $this->_revisionId) {
$element = $elementType::find()
$element = $this->_elementQuery($elementType)
->draftId($this->_draftId)
->revisionId($this->_revisionId)
->provisionalDrafts($this->_provisional)
Expand Down Expand Up @@ -2156,7 +2161,7 @@ private function _elementById(
if ($elementId) {
// First check for a provisional draft, if we're open to it
if ($checkForProvisionalDraft) {
$element = $elementType::find()
$element = $this->_elementQuery($elementType)
->provisionalDrafts()
->draftOf($elementId)
->draftCreator($user)
Expand All @@ -2171,7 +2176,7 @@ private function _elementById(
}
}

$element = $elementType::find()
$element = $this->_elementQuery($elementType)
->id($elementId)
->siteId($siteId)
->preferSites($preferSites)
Expand All @@ -2185,7 +2190,7 @@ private function _elementById(

// finally, check for an unpublished draft
// (see https://github.com/craftcms/cms/issues/14199)
return $elementType::find()
return $this->_elementQuery($elementType)
->id($elementId)
->siteId($siteId)
->preferSites($preferSites)
Expand All @@ -2196,7 +2201,7 @@ private function _elementById(
}

if ($elementUid) {
return $elementType::find()
return $this->_elementQuery($elementType)
->uid($elementUid)
->siteId($siteId)
->preferSites($preferSites)
Expand All @@ -2208,6 +2213,16 @@ private function _elementById(
return null;
}

private function _elementQuery(string $elementType): ElementQueryInterface
{
/** @var string|ElementInterface $elementType */
$query = $elementType::find();
if ($query instanceof NestedElementQueryInterface) {
$query->ownerId($this->_ownerId);
}
return $query;
}

/**
* Creates a new element.
*
Expand Down
2 changes: 1 addition & 1 deletion src/elements/Entry.php
Original file line number Diff line number Diff line change
Expand Up @@ -1626,7 +1626,7 @@ public function createAnother(): ?self
'sectionId' => $this->sectionId,
'fieldId' => $this->fieldId,
'primaryOwnerId' => $this->getPrimaryOwnerId(),
'ownerId' => $this->getPrimaryOwnerId(),
'ownerId' => $this->getOwnerId(),
'sortOrder' => null,
'typeId' => $this->typeId,
'siteId' => $this->siteId,
Expand Down
Loading
Loading