Skip to content

Instantly share code, notes, and snippets.

@pnomolos
Created July 21, 2011 21:18
Show Gist options
  • Save pnomolos/1098232 to your computer and use it in GitHub Desktop.
Save pnomolos/1098232 to your computer and use it in GitHub Desktop.
LS DB ActiveRecord HABTM extension for conditional joins
<?php
if (!class_exists('Db_ActiveRecord_habtm_ConditionalJoins')) {
class Db_ActiveRecord_habtm_ConditionalJoins extends Db_ActiveRecord {
public function get_relation_options($type, $name, &$has_primary_key, &$has_foreign_key) {
$backtrace = debug_backtrace(false);
$options = parent::get_relation_options($type, $name, $has_primary_key, $has_foreign_key);
// TODO: I am very aware that this is a massive hack. Still looking for a way around it.
if ( $backtrace[1]['function'] == 'formFieldGetOptions' ) { return $options; }
if ( $type == 'has_and_belongs_to_many' ) {
$settings = $this->has_and_belongs_to_many[$name];
if ( isset( $settings['join_conditions'] ) || isset( $settings['join_fields'] ) ) {
$condition = ( isset( $settings['conditions'] ) ? ($settings['conditions']) . ' AND ' : null );
$this->has_and_belongs_to_many[$name]['old_conditions'] =
( isset( $settings['conditions'] ) ? $settings['conditions'] : null );
$join_conditions = isset( $settings['join_conditions'] ) ? $settings['join_conditions'] : '';
if ( isset( $settings['join_fields'] ) ) {
if ( $join_conditions ) {
$join_conditions .= ' AND ';
}
$fields = array();
foreach ( $settings['join_fields'] as $field_name => $value ) {
$fields[] = "{$field_name}='" . mysql_real_escape_string( $value ) . "'";
}
$join_conditions .= '(' . join(' AND ', $fields) . ')';
}
if ( $join_conditions ) {
$options['conditions'] = '(' . $condition . "({$join_conditions})" . ')';
}
}
}
return $options;
}
protected function custom_relation_save() {
foreach ($this->changed_relations as $action => $relation) {
foreach ($relation as $name => $info) {
if ($info['type'] == 'has_and_belongs_to_many') {
// Most of the following code is taken from db_activerecord.php in apply_relations_changes()
$defaults = array(
'class_name' => Phpr_Inflector::classify($name)
);
if (is_array($info['relation'])) {
$options = array_merge($defaults, $info['relation']);
} else {
$options = array_merge($defaults, array('class_name' => Phpr_Inflector::classify($info['relation'])));
}
// We're only handling the polymorphic associations
if ( !isset( $options['join_fields'] ) ) { continue; }
// Create model
$object = new $options['class_name']();
if (is_null($object)) {
throw new Phpr_SystemException('Class not found: '.$options['class_name']);
}
if (!isset($options['primary_key'])) {
$options['primary_key'] = Phpr_Inflector::foreign_key($this->table_name, $this->primary_key);
}
if (!isset($options['foreign_key'])) {
$options['foreign_key'] = Phpr_Inflector::foreign_key($object->table_name, $object->primary_key);
}
if (!isset($options['join_table'])) {
$options['join_table'] = $this->get_join_table_name($this->table_name, $object->table_name);
}
if ($action == 'bind') {
foreach ( $info['values'] as $value ) {
$fields_to_set = array(
$options['primary_key'] => $this->{$this->primary_key},
$options['foreign_key'] => $value
);
// Merge the values if we're joining with additional fields
if ( isset( $options['join_fields'] ) ) {
$fields_to_set = array_merge(
$fields_to_set,
$options['join_fields']
);
}
$this->sql_insert(
$options['join_table'],
$fields_to_set
);
}
} elseif ($action == 'unbind') {
$delete_statement = Db::where(
$options['primary_key'] . ' = ?',
$this->{$this->primary_key}
)->where(
$options['foreign_key'] . ' IN (?)',
array($info['values'])
);
// Make sure to add the additional fields
if ( isset( $options['join_fields'] ) ) {
foreach ( $options['join_fields'] as $field_name => $value ) {
$delete_statement->where( $field_name . '=?', array($value) );
}
}
$this->sql_delete(
$options['join_table'],
$delete_statement
);
}
unset ( $this->changed_relations[$action] );
} // 'has_and_belongs_to_many'
}
} // foreach
} // custom_relation_save
}
}
<?php
public $has_and_belongs_to_many = array(
'add_on_order_status'=>array(
'class_name'=>'Shop_StatusTransition',
'primary_key'=>'psinventory_param_id',
'foreign_key' => 'shop_status_transition_id',
'join_table' => 'psinventory_params_shop_status_transitions',
'join_fields' => array(
'transition_flag' => 'active'
)
),
'remove_on_order_status'=>array(
'class_name'=>'Shop_StatusTransition',
'primary_key'=>'psinventory_param_id',
'foreign_key' => 'shop_status_transition_id',
'join_table' => 'psinventory_params_shop_status_transitions',
'join_fields' => array(
'transition_flag' => 'reclaim'
)
),
'update_at_order_status'=>array(
'class_name'=>'Shop_OrderStatus',
'primary_key'=>'psinventory_param_id',
'foreign_key' => 'shop_status_transition_id',
'join_table' => 'psinventory_params_shop_status_transitions',
'join_fields' => array(
'transition_flag' => 'order_status'
)
)
);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment