Further work on the linkable behavior, since it wasn't working right with aliases. It doesn't help matters that models are instantiated from the model associations with their own alias. Thus, the priority of a tables alias is 1) 'alias' as defined in the 'link' structure'; 2) alias member of the model instance; 3) class name of the model instance. I may need to revisit this work later, since while typing these comments I managed to enlighten myself on the alias scheme. But it does seem to work for now.
git-svn-id: file:///svn-source/pmgr/branches/ledger_transactions_20090605/site@140 97e9348a-65ac-dc4b-aefc-98561f571b83
This commit is contained in:
@@ -28,6 +28,50 @@
|
|||||||
*
|
*
|
||||||
* @version 1.0;
|
* @version 1.0;
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/**********************************************************************
|
||||||
|
* NOTE TO <AP> 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 {
|
class LinkableBehavior extends ModelBehavior {
|
||||||
|
|
||||||
@@ -66,7 +110,10 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
public function beforeFind(&$Model, $query) {
|
public function beforeFind(&$Model, $query) {
|
||||||
/* pr("Linkable::beforeFind() begin"); pr($query); */
|
/* pr("Linkable::beforeFind() begin"); pr($query); */
|
||||||
if (isset($query[$this->_key])) {
|
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);
|
$optionsKeys = $this->_options + array($this->_key => true);
|
||||||
if (!isset($query['fields']) || $query['fields'] === true) {
|
if (!isset($query['fields']) || $query['fields'] === true) {
|
||||||
//$query['fields'] = array_keys($Model->_schema);
|
//$query['fields'] = array_keys($Model->_schema);
|
||||||
@@ -85,6 +132,7 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
unset($iterator['defaults']);
|
unset($iterator['defaults']);
|
||||||
}
|
}
|
||||||
$iterations = Set::normalize($iterator);
|
$iterations = Set::normalize($iterator);
|
||||||
|
/* pr(compact('iterations')); */
|
||||||
foreach ($iterations as $alias => $options) {
|
foreach ($iterations as $alias => $options) {
|
||||||
if (is_null($options)) {
|
if (is_null($options)) {
|
||||||
$options = array();
|
$options = array();
|
||||||
@@ -95,14 +143,17 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (empty($options['table']) && empty($options['class'])) {
|
if (empty($options['table']) && empty($options['class'])) {
|
||||||
$options['class'] = $options['alias'];
|
$options['class'] = $alias;
|
||||||
} elseif (!empty($options['table']) && empty($options['class'])) {
|
} elseif (!empty($options['table']) && empty($options['class'])) {
|
||||||
$options['class'] = Inflector::classify($options['table']);
|
$options['class'] = Inflector::classify($options['table']);
|
||||||
}
|
}
|
||||||
|
/* pr(compact('alias', 'options')); */
|
||||||
$_Model =& ClassRegistry::init($options['class']); // the incoming model to be linked in query
|
$_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
|
$Reference =& ClassRegistry::init($options['reference']['class']); // the already in query model that links to $_Model
|
||||||
/* pr("_Model: $options[class] : $_Model->name ($_Model->alias)"); */
|
/* pr("_Model: {$options['alias']} : {$options['class']}" . */
|
||||||
/* pr("Reference: $options[reference] : $Reference->name ($Reference->alias)"); */
|
/* " ({$_Model->alias} : {$_Model->name})"); */
|
||||||
|
/* pr("Reference: {$options['reference']['alias']} : {$options['reference']['class']}" . */
|
||||||
|
/* " ({$Reference->alias} : {$Reference->name})"); */
|
||||||
$db =& $_Model->getDataSource();
|
$db =& $_Model->getDataSource();
|
||||||
|
|
||||||
$associatedThroughReference = 0;
|
$associatedThroughReference = 0;
|
||||||
@@ -135,18 +186,22 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
|
|
||||||
if ($associatedThroughReference)
|
if ($associatedThroughReference)
|
||||||
$this->recursive_array_replace("%{MODEL_ALIAS}",
|
$this->recursive_array_replace("%{MODEL_ALIAS}",
|
||||||
$Reference->alias,
|
$options['reference']['alias'],
|
||||||
$association['conditions']);
|
$association['conditions']);
|
||||||
else
|
else
|
||||||
$this->recursive_array_replace("%{MODEL_ALIAS}",
|
$this->recursive_array_replace("%{MODEL_ALIAS}",
|
||||||
$_Model->alias,
|
$options['alias'],
|
||||||
$association['conditions']);
|
$association['conditions']);
|
||||||
|
|
||||||
// Determine which model holds the foreign key
|
// Determine which model holds the foreign key
|
||||||
if (($type === 'hasMany' || $type === 'hasOne') ^ $associatedThroughReference) {
|
if (($type === 'hasMany' || $type === 'hasOne') ^ $associatedThroughReference) {
|
||||||
|
$primaryAlias = $options['reference']['alias'];
|
||||||
|
$foreignAlias = $options['alias'];
|
||||||
$primaryModel = $Reference;
|
$primaryModel = $Reference;
|
||||||
$foreignModel = $_Model;
|
$foreignModel = $_Model;
|
||||||
} else {
|
} else {
|
||||||
|
$primaryAlias = $options['alias'];
|
||||||
|
$foreignAlias = $options['reference']['alias'];
|
||||||
$primaryModel = $_Model;
|
$primaryModel = $_Model;
|
||||||
$foreignModel = $Reference;
|
$foreignModel = $Reference;
|
||||||
}
|
}
|
||||||
@@ -188,8 +243,8 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
$referenceLink = $Link->escapeField(Inflector::underscore($Reference->alias) . '_id', $linkAlias);
|
$referenceLink = $Link->escapeField(Inflector::underscore($Reference->alias) . '_id', $linkAlias);
|
||||||
|
|
||||||
// Get the primary key from the tables we're joining.
|
// Get the primary key from the tables we're joining.
|
||||||
$referenceKey = $Reference->escapeField();
|
$referenceKey = $Reference->escapeField(null, $options['reference']['alias']);
|
||||||
$modelKey = $_Model->escapeField();
|
$modelKey = $_Model->escapeField(null, $options['alias']);
|
||||||
|
|
||||||
// Join the linkage table to our model. We'll use an inner join,
|
// 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
|
// as the whole purpose of the linkage table is to make this
|
||||||
@@ -210,8 +265,8 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
$options['conditions'][] = "{$referenceLink} = {$referenceKey}";
|
$options['conditions'][] = "{$referenceLink} = {$referenceKey}";
|
||||||
}
|
}
|
||||||
elseif (isset($association['foreignKey']) && $association['foreignKey']) {
|
elseif (isset($association['foreignKey']) && $association['foreignKey']) {
|
||||||
$foreignKey = $primaryModel->escapeField($association['foreignKey']);
|
$foreignKey = $primaryModel->escapeField($association['foreignKey'], $primaryAlias);
|
||||||
$primaryKey = $foreignModel->escapeField($foreignModel->primaryKey);
|
$primaryKey = $foreignModel->escapeField($foreignModel->primaryKey, $foreignAlias);
|
||||||
|
|
||||||
// Only differentiating to help show the logical flow.
|
// Only differentiating to help show the logical flow.
|
||||||
// Either way works and this test can be tossed out
|
// Either way works and this test can be tossed out
|
||||||
@@ -232,29 +287,31 @@ class LinkableBehavior extends ModelBehavior {
|
|||||||
elseif (!empty($association['conditions']))
|
elseif (!empty($association['conditions']))
|
||||||
$options['conditions'][] = $association['conditions'];
|
$options['conditions'][] = $association['conditions'];
|
||||||
|
|
||||||
/* pr(array("Link ", $options['conditions'])); */
|
|
||||||
//pr($modelKey);
|
|
||||||
//pr($referenceKey);
|
|
||||||
|
|
||||||
}
|
}
|
||||||
if (empty($options['table'])) {
|
if (empty($options['table'])) {
|
||||||
$options['table'] = $db->fullTableName($_Model, true);
|
$options['table'] = $db->fullTableName($_Model, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!isset($options['fields']) || !is_array($options['fields']))
|
if (!isset($options['fields']) || !is_array($options['fields']))
|
||||||
$options['fields'] = $db->fields($_Model);
|
$options['fields'] = $db->fields($_Model, $options['alias']);
|
||||||
elseif (!empty($options['fields']))
|
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'],
|
$query['fields'] = array_merge($query['fields'], $options['fields'],
|
||||||
(empty($association['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[$this->_key] = am($options[$this->_key], array_diff_key($options, $optionsKeys));
|
||||||
$options = array_intersect_key($options, $optionsKeys);
|
$options = array_intersect_key($options, $optionsKeys);
|
||||||
if (!empty($options[$this->_key])) {
|
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));
|
$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]);
|
$notDone = isset($iterators[$cont]);
|
||||||
} while ($notDone);
|
} while ($notDone);
|
||||||
}
|
}
|
||||||
/* pr("Linkable::beforeFind() end"); pr($query); */
|
/* pr(array('checkpoint' => 'Linkable::beforeFind() end', */
|
||||||
|
/* compact('query'))); */
|
||||||
return $query;
|
return $query;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
Reference in New Issue
Block a user