Skip to content
Snippets Groups Projects
Commit dfb6f127 authored by Peter Rotich's avatar Peter Rotich
Browse files

cdata: Make DynamicDataView generic

This is necessary to allow objects to register data views on the fly.
parent e54acbf8
No related branches found
No related tags found
No related merge requests found
...@@ -94,8 +94,10 @@ class Bootstrap { ...@@ -94,8 +94,10 @@ class Bootstrap {
define('THREAD_ENTRY_TABLE', $prefix.'thread_entry'); define('THREAD_ENTRY_TABLE', $prefix.'thread_entry');
define('THREAD_ENTRY_EMAIL_TABLE', $prefix.'thread_entry_email'); define('THREAD_ENTRY_EMAIL_TABLE', $prefix.'thread_entry_email');
define('TICKET_TABLE',$prefix.'ticket');
define('LOCK_TABLE',$prefix.'lock'); define('LOCK_TABLE',$prefix.'lock');
define('TICKET_TABLE',$prefix.'ticket');
define('TICKET_CDATA_TABLE', $prefix.'ticket__cdata');
define('TICKET_EVENT_TABLE',$prefix.'ticket_event'); define('TICKET_EVENT_TABLE',$prefix.'ticket_event');
define('THREAD_COLLABORATOR_TABLE', $prefix.'thread_collaborator'); define('THREAD_COLLABORATOR_TABLE', $prefix.'thread_collaborator');
define('TICKET_STATUS_TABLE', $prefix.'ticket_status'); define('TICKET_STATUS_TABLE', $prefix.'ticket_status');
......
...@@ -254,6 +254,87 @@ class DynamicForm extends VerySimpleModel { ...@@ -254,6 +254,87 @@ class DynamicForm extends VerySimpleModel {
return true; return true;
} }
static function ensureDynamicDataView() {
if (!($cdata=static::$cdata) || !$cdata['table'])
return false;
$sql = 'SHOW TABLES LIKE \''.$cdata['table'].'\'';
if (!db_num_rows(db_query($sql)))
return static::buildDynamicDataView($cdata);
}
static function buildDynamicDataView($cdata) {
$sql = 'CREATE TABLE `'.$cdata['table'].'` (PRIMARY KEY
('.$cdata['object_id'].')) AS '
. static::getCrossTabQuery( $cdata['object_type'], $cdata['object_id']);
db_query($sql);
}
static function dropDynamicDataView($table) {
db_query('DROP TABLE IF EXISTS `'.$table.'`');
}
static function updateDynamicDataView($answer, $data) {
// TODO: Detect $data['dirty'] for value and value_id
// We're chiefly concerned with Ticket form answers
$cdata = static::$cdata;
if (!$cdata
|| !$cdata['table']
|| !($e = $answer->getEntry())
|| $e->getForm()->get('type') != $cdata['object_type'])
return;
// $record = array();
// $record[$f] = $answer->value'
// TicketFormData::objects()->filter(array('ticket_id'=>$a))
// ->merge($record);
$sql = 'SHOW TABLES LIKE \''.$cdata['table'].'\'';
if (!db_num_rows(db_query($sql)))
return;
$f = $answer->getField();
$name = $f->get('name') ? $f->get('name')
: 'field_'.$f->get('id');
$fields = sprintf('`%s`=', $name) . db_input(
implode(',', $answer->getSearchKeys()));
$sql = 'INSERT INTO `'.$cdata['table'].'` SET '.$fields
. sprintf(', `%s`= %s',
$cdata['object_id'],
db_input($answer->getEntry()->get('object_id')))
.' ON DUPLICATE KEY UPDATE '.$fields;
if (!db_query($sql) || !db_affected_rows())
return self::dropDynamicDataView($cdata['table']);
}
static function updateDynamicFormEntryAnswer($answer, $data) {
if (!$answer
|| !($e = $answer->getEntry())
|| !$e->getForm())
return;
switch ($e->getForm()->get('type')) {
case 'T':
return TicketForm::updateDynamicDataView($answer, $data);
case 'A':
return TaskForm::updateDynamicDataView($answer, $data);
}
}
static function updateDynamicFormField($field, $data) {
if (!$field || !$field->getForm())
return;
switch ($field->getForm()->get('type')) {
case 'T':
return TicketForm::dropDynamicDataView(TicketForm::$cdata['table']);
case 'A':
return TaskForm::dropDynamicDataView(TicketForm::$cdata['table']);
}
}
static function getCrossTabQuery($object_type, $object_id='object_id', $exclude=array()) { static function getCrossTabQuery($object_type, $object_id='object_id', $exclude=array()) {
$fields = static::getDynamicDataViewFields($exclude); $fields = static::getDynamicDataViewFields($exclude);
...@@ -264,8 +345,7 @@ class DynamicForm extends VerySimpleModel { ...@@ -264,8 +345,7 @@ class DynamicForm extends VerySimpleModel {
WHERE entry.object_type='$object_type' GROUP BY entry.object_id"; WHERE entry.object_type='$object_type' GROUP BY entry.object_id";
} }
// Materialized View for Ticket custom data (MySQL FlexViews would be // Materialized View for custom data (MySQL FlexViews would be nice)
// nice)
// //
// @see http://code.google.com/p/flexviews/ // @see http://code.google.com/p/flexviews/
static function getDynamicDataViewFields($exclude) { static function getDynamicDataViewFields($exclude) {
...@@ -347,6 +427,12 @@ Filter::addSupportedMatches(/* @trans */ 'User Data', function() { ...@@ -347,6 +427,12 @@ Filter::addSupportedMatches(/* @trans */ 'User Data', function() {
class TicketForm extends DynamicForm { class TicketForm extends DynamicForm {
static $instance; static $instance;
static $cdata = array(
'table' => TICKET_CDATA_TABLE,
'object_id' => 'ticket_id',
'object_type' => 'T',
);
static function objects() { static function objects() {
$os = parent::objects(); $os = parent::objects();
return $os->filter(array('type'=>'T')); return $os->filter(array('type'=>'T'));
...@@ -435,27 +521,24 @@ Filter::addSupportedMatches(/* @trans */ 'Ticket Data', function() { ...@@ -435,27 +521,24 @@ Filter::addSupportedMatches(/* @trans */ 'Ticket Data', function() {
}, 30); }, 30);
// Manage materialized view on custom data updates // Manage materialized view on custom data updates
Signal::connect('model.created', Signal::connect('model.created',
array('TicketForm', 'updateDynamicDataView'), array('DynamicForm', 'updateDynamicFormEntryAnswer'),
'DynamicFormEntryAnswer'); 'DynamicFormEntryAnswer');
Signal::connect('model.updated', Signal::connect('model.updated',
array('TicketForm', 'updateDynamicDataView'), array('DynamicForm', 'updateDynamicFormEntryAnswer'),
'DynamicFormEntryAnswer'); 'DynamicFormEntryAnswer');
// Recreate the dynamic view after new or removed fields to the ticket // Recreate the dynamic view after new or removed fields to the ticket
// details form // details form
Signal::connect('model.created', Signal::connect('model.created',
array('TicketForm', 'dropDynamicDataView'), array('DynamicForm', 'updateDynamicFormField'),
'DynamicFormField', 'DynamicFormField');
function($o) { return $o->form->type == 'T'; });
Signal::connect('model.deleted', Signal::connect('model.deleted',
array('TicketForm', 'dropDynamicDataView'), array('DynamicForm', 'updateDynamicFormField'),
'DynamicFormField', 'DynamicFormField');
function($o) { return $o->form->type == 'T'; });
// If the `name` column is in the dirty list, we would be renaming a // If the `name` column is in the dirty list, we would be renaming a
// column. Delete the view instead. // column. Delete the view instead.
Signal::connect('model.updated', Signal::connect('model.updated',
array('TicketForm', 'dropDynamicDataView'), array('DynamicForm', 'updateDynamicFormField'),
'DynamicFormField', 'DynamicFormField',
// TODO: Lookup the dynamic form to verify {type == 'T'}
function($o, $d) { return isset($d['dirty']) function($o, $d) { return isset($d['dirty'])
&& (isset($d['dirty']['name']) || isset($d['dirty']['type'])); }); && (isset($d['dirty']['name']) || isset($d['dirty']['type'])); });
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment