From 3aa01b92fd8fa64b1136ab5cd5fd8c0b8c52515d Mon Sep 17 00:00:00 2001 From: Benn Oshrin Date: Thu, 22 Aug 2019 17:22:02 -0700 Subject: [PATCH] Fix handling of primary link in breadcrumbs (CO-1766) --- app/src/Controller/AppController.php | 111 +++++++++++++--------- app/src/Lib/Traits/MatchgridLinkTrait.php | 2 +- app/src/Lib/Traits/PrimaryLinkTrait.php | 16 ++++ app/src/Template/Element/breadcrumbs.ctp | 6 +- 4 files changed, 86 insertions(+), 49 deletions(-) diff --git a/app/src/Controller/AppController.php b/app/src/Controller/AppController.php index 7e3af70a6..afe6c2366 100644 --- a/app/src/Controller/AppController.php +++ b/app/src/Controller/AppController.php @@ -41,48 +41,8 @@ class AppController extends Controller { // and so should not be trusted without further authorization. protected $cur_mg = null; - /** - * Obtain information about the Standard Object's Primary Link, if set. - * The $vv_primary_link view variable is also set. - * - * @since COmanage Match v1.0.0 - * @param boolean $lookup If true, get the value of the primary link, not just the attribute - * @return array Array holding the primary link attribute, and optionally its value - * @throws \RuntimeException - */ - - protected function getPrimaryLink(bool $lookup=false) { - // $this->name = Models - $modelsName = $this->name; - // $modelName = Model - $modelName = \Cake\Utility\Inflector::singularize($this->name); - - $ret = []; - - // PrimaryLinkTrait - if(method_exists($this->$modelsName, "getPrimaryLink") - && $this->$modelsName->getPrimaryLink()) { - $ret['linkattr'] = $this->$modelsName->getPrimaryLink(); - $this->set('vv_primary_link', $ret['linkattr']); - - if($lookup) { - // Try to find a value - if($this->request->getQuery($ret['linkattr'])) { - $ret['linkvalue'] = $this->request->getQuery($ret['linkattr']); - } elseif($this->request->getData($ret['linkattr'])) { - $ret['linkvalue'] = $this->request->getData($ret['linkattr']); - } elseif($this->request->getData($modelName . "." . $ret['linkattr'])) { - $ret['linkvalue'] = $this->request->getData($modelName . "." . $ret['linkattr']); - } else { - if(!$this->$modelsName->allowEmptyPrimaryLink()) { - throw new \RuntimeException(__('match.er.primary_link', [ $ret['linkattr'] ])); - } - } - } - } - - return $ret; - } + // If set, the current primary link. + protected $cur_pl = null; /** * Initialization callback. @@ -180,6 +140,65 @@ public function beforeRender(\Cake\Event\Event $event) { } } + /** + * Obtain information about the Standard Object's Primary Link, if set. + * The $vv_primary_link view variable is also set. + * + * @since COmanage Match v1.0.0 + * @param boolean $lookup If true, get the value of the primary link, not just the attribute + * @return array Array holding the primary link attribute, and optionally its value + * @throws \RuntimeException + */ + + protected function getPrimaryLink(bool $lookup=false) { + // Did we already figure this out? + if($this->cur_pl) { + return $this->cur_pl; + } + + // $this->name = Models + $modelsName = $this->name; + // $modelName = Model + $modelName = \Cake\Utility\Inflector::singularize($this->name); + + $this->cur_pl = []; + + // PrimaryLinkTrait + if(method_exists($this->$modelsName, "getPrimaryLink") + && $this->$modelsName->getPrimaryLink()) { + $this->cur_pl['linkattr'] = $this->$modelsName->getPrimaryLink(); + $this->set('vv_primary_link', $this->cur_pl['linkattr']); + + if($lookup) { + // Try to find a value + if($this->request->getQuery($this->cur_pl['linkattr'])) { + $this->cur_pl['linkvalue'] = $this->request->getQuery($this->cur_pl['linkattr']); + } elseif($this->request->getData($this->cur_pl['linkattr'])) { + $this->cur_pl['linkvalue'] = $this->request->getData($this->cur_pl['linkattr']); + } elseif($this->request->getData($modelName . "." . $this->cur_pl['linkattr'])) { + $this->cur_pl['linkvalue'] = $this->request->getData($modelName . "." . $this->cur_pl['linkattr']); + } else { + // Try to map via the requested ID, if known + $param = (int)$this->request->getParam('pass.0'); + + if(!empty($param)) { + $this->cur_pl['linkvalue'] = $this->$modelsName->calculateMatchgridId($param); + } + + if(!$this->cur_pl['linkvalue'] && !$this->$modelsName->allowEmptyPrimaryLink()) { + throw new \RuntimeException(__('match.er.primary_link', [ $this->cur_pl['linkattr'] ])); + } + } + } + + if(!empty($this->cur_pl['linkvalue'])) { + $this->set('vv_primary_link_id', $this->cur_pl['linkvalue']); + } + } + + return $this->cur_pl; + } + /** * Determine the (requested) current Matchgrid and make it available to the * rest of the application. @@ -201,6 +220,11 @@ protected function setMatchgrid() { return; } + // Not all models have matchgrid as their primary link. This will trigger + // setting of the viewVar for breadcrumbs and anything else. + // PrimaryLinkTrait + $link = $this->getPrimaryLink(true); + // Try to find the requested matchgrid $mgid = null; @@ -234,9 +258,6 @@ protected function setMatchgrid() { if(!$mgid) { // Use the primary link (if found) to calculate the matchgrid ID - // PrimaryLinkTrait - $link = $this->getPrimaryLink(true); - if(!empty($link['linkvalue'])) { $m = \Cake\Utility\Inflector::pluralize( \Cake\Utility\Inflector::camelize( diff --git a/app/src/Lib/Traits/MatchgridLinkTrait.php b/app/src/Lib/Traits/MatchgridLinkTrait.php index e90a81229..8fafd9bfd 100644 --- a/app/src/Lib/Traits/MatchgridLinkTrait.php +++ b/app/src/Lib/Traits/MatchgridLinkTrait.php @@ -67,7 +67,7 @@ public function allowUnkeyedMatchgrid(string $action) { * Calculate the Matchgrid ID associated with the requested object ID. * * @since COmanage Match v1.0.0 - * @param int $id Matchgrid ID + * @param int $id Object ID * @return int Matchgrid ID * @throws Cake\Datasource\Exception\RecordNotFoundException */ diff --git a/app/src/Lib/Traits/PrimaryLinkTrait.php b/app/src/Lib/Traits/PrimaryLinkTrait.php index 3acd00ca0..f1e74a662 100644 --- a/app/src/Lib/Traits/PrimaryLinkTrait.php +++ b/app/src/Lib/Traits/PrimaryLinkTrait.php @@ -47,6 +47,22 @@ public function allowEmptyPrimaryLink() { return $this->allowEmpty; } + /** + * Calculate the Primary Link ID associated with the requested object ID. + * + * @since COmanage Match v1.0.0 + * @param int $id Object ID + * @return int Primary Link ID + * @throws Cake\Datasource\Exception\RecordNotFoundException + */ + + public function calculatePrimaryLinkId(int $id) { + $obj = $this->findById($id)->firstOrFail(); + //select([$this->primaryLink]); + + return $obj->${$this->primaryLink}; + } + /** * Generate an ORM Query for the Primary Link. * diff --git a/app/src/Template/Element/breadcrumbs.ctp b/app/src/Template/Element/breadcrumbs.ctp index fb5a5360d..63ee620a7 100644 --- a/app/src/Template/Element/breadcrumbs.ctp +++ b/app/src/Template/Element/breadcrumbs.ctp @@ -60,15 +60,15 @@ if($this->request->getRequestTarget(false) != '/') { if($action != 'index' && ($modelsName != 'Matchgrids' && $action != 'pending')) { - // Default parent is index, to which we might need to append the Matchgrid ID + // Default parent is index, to which we might need to append the Primary Link ID $target = [ 'controller' => $tableName, 'action' => 'index' ]; - if(!empty($vv_cur_mg)) { - $target['matchgrid_id'] = $vv_cur_mg->id; + if(!empty($vv_primary_link) && !empty($vv_primary_link_id)) { + $target[$vv_primary_link] = $vv_primary_link_id; } $this->Breadcrumbs->add(