diff --git a/models/behaviors/linkable.php b/models/behaviors/linkable.php index 676059f..7e9b44b 100644 --- a/models/behaviors/linkable.php +++ b/models/behaviors/linkable.php @@ -28,6 +28,50 @@ * * @version 1.0; */ + + +/********************************************************************** + * NOTE TO 20090615: + * This structure should be linkable (it was my test case). + + $entry = $this->LedgerEntry->find + ('first', + array('link' => array('DebitLedger' => + array( + 'fields' => array('id'), + 'alias' => 'MyDebitLedger', + 'Account' => + array( + 'fields' => array('id'), + 'alias' => 'MyDebitAccount'), + ), + + 'MyCreditLedger' => + array( + 'fields' => array('id'), + 'class' => 'CreditLedger', + 'MyCreditAccount' => + array( + 'fields' => array('id'), + 'class' => 'Account'), + ), + + 'MyOtherLedger' => + array( + 'fields' => array('id'), + 'class' => 'Ledger', + 'alias' => 'AliasToMyOtherLedger', + 'Account' => + array( + 'fields' => array('id'), + 'alias' => 'AliasToMyOtherAccount'), + ), + ), + + 'conditions' => array('LedgerEntry.id' => $id), + )); +**********************************************************************/ + class LinkableBehavior extends ModelBehavior { @@ -66,7 +110,10 @@ class LinkableBehavior extends ModelBehavior { public function beforeFind(&$Model, $query) { /* pr("Linkable::beforeFind() begin"); pr($query); */ if (isset($query[$this->_key])) { - $optionsDefaults = $this->_defaults + array('reference' => $Model->alias, $this->_key => array()); + $optionsDefaults = $this->_defaults + array('reference' => + array('class' => $Model->alias, + 'alias' => $Model->alias), + $this->_key => array()); $optionsKeys = $this->_options + array($this->_key => true); if (!isset($query['fields']) || $query['fields'] === true) { //$query['fields'] = array_keys($Model->_schema); @@ -85,6 +132,7 @@ class LinkableBehavior extends ModelBehavior { unset($iterator['defaults']); } $iterations = Set::normalize($iterator); +/* pr(compact('iterations')); */ foreach ($iterations as $alias => $options) { if (is_null($options)) { $options = array(); @@ -95,14 +143,17 @@ class LinkableBehavior extends ModelBehavior { } if (empty($options['table']) && empty($options['class'])) { - $options['class'] = $options['alias']; + $options['class'] = $alias; } elseif (!empty($options['table']) && empty($options['class'])) { $options['class'] = Inflector::classify($options['table']); } +/* pr(compact('alias', 'options')); */ $_Model =& ClassRegistry::init($options['class']); // the incoming model to be linked in query - $Reference =& ClassRegistry::init($options['reference']); // the already in query model that links to $_Model -/* pr("_Model: $options[class] : $_Model->name ($_Model->alias)"); */ -/* pr("Reference: $options[reference] : $Reference->name ($Reference->alias)"); */ + $Reference =& ClassRegistry::init($options['reference']['class']); // the already in query model that links to $_Model +/* pr("_Model: {$options['alias']} : {$options['class']}" . */ +/* " ({$_Model->alias} : {$_Model->name})"); */ +/* pr("Reference: {$options['reference']['alias']} : {$options['reference']['class']}" . */ +/* " ({$Reference->alias} : {$Reference->name})"); */ $db =& $_Model->getDataSource(); $associatedThroughReference = 0; @@ -135,18 +186,22 @@ class LinkableBehavior extends ModelBehavior { if ($associatedThroughReference) $this->recursive_array_replace("%{MODEL_ALIAS}", - $Reference->alias, + $options['reference']['alias'], $association['conditions']); else $this->recursive_array_replace("%{MODEL_ALIAS}", - $_Model->alias, + $options['alias'], $association['conditions']); // Determine which model holds the foreign key if (($type === 'hasMany' || $type === 'hasOne') ^ $associatedThroughReference) { + $primaryAlias = $options['reference']['alias']; + $foreignAlias = $options['alias']; $primaryModel = $Reference; $foreignModel = $_Model; } else { + $primaryAlias = $options['alias']; + $foreignAlias = $options['reference']['alias']; $primaryModel = $_Model; $foreignModel = $Reference; } @@ -188,8 +243,8 @@ class LinkableBehavior extends ModelBehavior { $referenceLink = $Link->escapeField(Inflector::underscore($Reference->alias) . '_id', $linkAlias); // Get the primary key from the tables we're joining. - $referenceKey = $Reference->escapeField(); - $modelKey = $_Model->escapeField(); + $referenceKey = $Reference->escapeField(null, $options['reference']['alias']); + $modelKey = $_Model->escapeField(null, $options['alias']); // Join the linkage table to our model. We'll use an inner join, // as the whole purpose of the linkage table is to make this @@ -210,8 +265,8 @@ class LinkableBehavior extends ModelBehavior { $options['conditions'][] = "{$referenceLink} = {$referenceKey}"; } elseif (isset($association['foreignKey']) && $association['foreignKey']) { - $foreignKey = $primaryModel->escapeField($association['foreignKey']); - $primaryKey = $foreignModel->escapeField($foreignModel->primaryKey); + $foreignKey = $primaryModel->escapeField($association['foreignKey'], $primaryAlias); + $primaryKey = $foreignModel->escapeField($foreignModel->primaryKey, $foreignAlias); // Only differentiating to help show the logical flow. // Either way works and this test can be tossed out @@ -232,29 +287,31 @@ class LinkableBehavior extends ModelBehavior { elseif (!empty($association['conditions'])) $options['conditions'][] = $association['conditions']; -/* pr(array("Link ", $options['conditions'])); */ - //pr($modelKey); - //pr($referenceKey); - } if (empty($options['table'])) { $options['table'] = $db->fullTableName($_Model, true); } if (!isset($options['fields']) || !is_array($options['fields'])) - $options['fields'] = $db->fields($_Model); + $options['fields'] = $db->fields($_Model, $options['alias']); elseif (!empty($options['fields'])) - $options['fields'] = $db->fields($_Model, null, $options['fields']); + $options['fields'] = $db->fields($_Model, $options['alias'], $options['fields']); $query['fields'] = array_merge($query['fields'], $options['fields'], (empty($association['fields']) - ? array() : $db->fields($_Model, null, $association['fields']))); + ? array() : $db->fields($_Model, $options['alias'], $association['fields']))); +/* pr(array('checkpoint' => 'Model Work Complete', compact('options'))); */ $options[$this->_key] = am($options[$this->_key], array_diff_key($options, $optionsKeys)); $options = array_intersect_key($options, $optionsKeys); if (!empty($options[$this->_key])) { - $iterators[] = $options[$this->_key] + array('defaults' => array_merge($defaults, array('reference' => $options['class']))); + $iterators[] = $options[$this->_key] + + array('defaults' => + array_merge($defaults, + array('reference' => + array('class' => $options['class'], + 'alias' => $options['alias'])))); } $query['joins'][] = array_intersect_key($options, array('type' => true, 'alias' => true, 'table' => true, 'joins' => true, 'conditions' => true)); } @@ -262,7 +319,8 @@ class LinkableBehavior extends ModelBehavior { $notDone = isset($iterators[$cont]); } while ($notDone); } -/* pr("Linkable::beforeFind() end"); pr($query); */ +/* pr(array('checkpoint' => 'Linkable::beforeFind() end', */ +/* compact('query'))); */ return $query; } } \ No newline at end of file