From 1d080dad9ea0f63b56f0ad4ba5a71ffc16a11ab5 Mon Sep 17 00:00:00 2001 From: jcarter Date: Tue, 12 Feb 2019 09:59:52 +1100 Subject: [PATCH] fix(ModelAdmin): Workaround for silverstripe-recipe 4.3.0 - Primary takeaway: this allows a site to use multisites with silverstripe-recipe 4.3.0 - Silverstripe-recipe 4.3.0 introduced changes that broke the previous approach to retrieving the model class. - This will be fixed in silverstripe-recipe 4.3.1 (really silverstripe-admin 1.3.1). - Don't want to require a specific version of ss-admin as it will create composer conflicts. - This commit changes multisites to only work with ss-recipe >= 4.3.0 - When using ss-recipe 4.3.0: - An error will be thrown if you use the MultisitesAware extension. - Else MultisitesAware will be bypassed. - Will work with ss-recipe >= 4.3.1 (other potential issues aside). --- composer.json | 3 +- src/Admin/MultisitesModelAdminExtension.php | 106 +++++++++++++------- 2 files changed, 74 insertions(+), 35 deletions(-) diff --git a/composer.json b/composer.json index 1fed703..593ee43 100644 --- a/composer.json +++ b/composer.json @@ -13,6 +13,7 @@ "require": { "silverstripe/cms": "~4.0", + "silverstripe/admin": "^4.3", "symbiote/silverstripe-multivaluefield": "~5.0" }, "require-dev": { @@ -24,7 +25,7 @@ ], "installer-name": "multisites", "branch-alias": { - "dev-master": "5.0.x-dev" + "dev-master": "5.2.x-dev" } }, "replace": { diff --git a/src/Admin/MultisitesModelAdminExtension.php b/src/Admin/MultisitesModelAdminExtension.php index 967d305..4f8de26 100644 --- a/src/Admin/MultisitesModelAdminExtension.php +++ b/src/Admin/MultisitesModelAdminExtension.php @@ -9,6 +9,7 @@ use SilverStripe\Core\Extension; use Symbiote\Multisites\Multisites; use Symbiote\Multisites\Model\Site; +use Symbiote\Multisites\Extension\MultisitesAware; /** * MultisitesModelAdminExtension @@ -16,7 +17,7 @@ * @package silverstripe-multisites */ class MultisitesModelAdminExtension extends Extension { - + private static $allowed_actions = array( 'updateSiteFilter' ); @@ -27,7 +28,7 @@ class MultisitesModelAdminExtension extends Extension { * @var DataObject **/ private $listDataClass; - + /** * If this dataClass is MultisitesAware, set the Multisites_ActiveSite * session variable to one of the follwing: @@ -35,16 +36,18 @@ class MultisitesModelAdminExtension extends Extension { * b) The current site, if the current member is a manager of that site * c) The first site that the current member is a manager of **/ - public function onAfterInit(){ - if($this->modelIsMultiSitesAware()) { + public function onAfterInit(){ + // throws exception if using ss-recipe <= 4.3.0 and using MultiSitesAware + $this->checkMultisitesAware(); + if($this->modelIsMultiSitesAware()) { if($siteID = $this->owner->getRequest()->requestVar('SiteID')){ $this->setActiveSite($siteID); } if(!$this->getActiveSite()){ $managedByMember = Multisites::inst()->sitesManagedByMember(); - + if(count($managedByMember)){ $currentSiteID = Multisites::inst()->getCurrentSiteId(); if(in_array($currentSiteID, $managedByMember)){ @@ -58,7 +61,27 @@ public function onAfterInit(){ } } - + /** + * Prevents use of MultisitesAware extension when using + * silvestripe-recipe <= 4.3.0 + * + * @return void + */ + public function checkMultisitesAware() { + // only true if using silverstripe-recipe <= 4.3.0 + if (!$this->owner->hasMethod('getModelClass')) { + $models = $this->owner->getManagedModels(); + // throw error if any models use MultisitesAware extension + foreach ($models as $model => $val) { + if($model::has_extension(MultisitesAware::class)) { + throw new \Exception( + '`ModelAdmin::getModelClass()` missing. You are likely using `silverstripe-recipe:4.3.0` which introduced this bug. This can be fixed by updating to `silverstripe-recipe:4.3.1` or greater.' + ); + } + } + } + } + /** * If this dataClass is MultisitesAware, filter the list by the current Multisites_ActiveSite **/ @@ -71,7 +94,6 @@ public function updateList(&$list){ } } - /** * If the current member is not a "Manager" of any sites, they shouldn't be able to manage MultisitesAware DataObjects. **/ @@ -88,7 +110,6 @@ public function updateEditForm($form){ } } - /** * Provide a Site filter **/ @@ -110,7 +131,6 @@ public function updateSearchForm($form){ } } - /** * get the active site for this model admin * @@ -128,7 +148,6 @@ public function getActiveSite() { } } - /** * Set the active site for this model admin * @@ -143,7 +162,6 @@ public function setActiveSite($siteID) { } } - /** * Get the key used to store this model admin active site Session to * @@ -153,27 +171,47 @@ public function getActiveSiteSessionKey() { return 'Multisites_ActiveSite_For_' . get_class($this->owner); } - - /** - * Get and cache an instance of the data class currently being listed - * - * @return DataObject - **/ - private function getListDataClass() { - if(!$this->listDataClass) { - $this->listDataClass = singleton($this->owner->getSearchContext()->getResults(array())->dataClass()); - } - return $this->listDataClass; - } - - - /** - * Determines whether the current model being managed is MultiSitesAware - * - * @return boolean - **/ - private function modelIsMultiSitesAware() { - $model = $this->getListDataClass(); - return $model->hasExtension('MultisitesAware') || $model instanceof SiteTree; - } + /** + * Get and cache an instance of the data class currently being listed + * + * @return DataObject + **/ + private function getListDataClass() { + /** + * Silverstripe-recipe 4.3.0 introduces changes that broke the + * previous approach to retrieving the model class. + * + * This is/will be fixed in silverstripe-recipe 4.3.1 + * + * We've taken this approach so that Multisites can work with + * SS 4.3.0 so long as you don't use the MultisitesAware extension. + */ + if ($this->listDataClass === null) { + // only true if silverstripe-recipe > 4.3.0 + if ($this->owner->hasMethod('getModelClass')) { + $this->listDataClass = $this->owner->getModelClass(); + } + // else false to bypass the MultisitesAware extension + else { + $this->listDataClass = false; + } + } + return $this->listDataClass; + } + + /** + * Determines whether the current model being managed is MultiSitesAware + * + * @return boolean + **/ + private function modelIsMultiSitesAware() { + $model = $this->getListDataClass(); + // always false if using silverstripe-recipe <= 4.3.0 + if ($model) { + $isAware = $model::has_extension(MultisitesAware::class); + $isSiteTree = in_array(SiteTree::class, ClassInfo::ancestry($model)); + return $isAware || $isSiteTree; + } + return false; + } }