Commit 27b55ab5 authored by colemanw's avatar colemanw Committed by GitHub

Merge pull request #10754 from totten/master-actcase-ts

CRM-20958 - Track creation+modification times for activities+cases
parents ff8784d5 ed30b249
......@@ -285,6 +285,10 @@ class CRM_Activity_BAO_Activity extends CRM_Activity_DAO_Activity {
* @return CRM_Activity_BAO_Activity|null|object
*/
public static function create(&$params) {
// CRM-20958 - These fields are managed by MySQL triggers. Watch out for clients resaving stale timestamps.
unset($params['created_date']);
unset($params['modified_date']);
// check required params
if (!self::dataExists($params)) {
throw new CRM_Core_Exception('Not enough data to create activity object');
......
......@@ -30,7 +30,7 @@
*
* Generated from xml/schema/CRM/Activity/Activity.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
* (GenCodeChecksum:a530f1fb1a27c5a15b5d138732b4c581)
* (GenCodeChecksum:dfa63754ef6ea1a9c7148e735dd6ff8a)
*/
require_once 'CRM/Core/DAO.php';
require_once 'CRM/Utils/Type.php';
......@@ -195,6 +195,18 @@ class CRM_Activity_DAO_Activity extends CRM_Core_DAO {
* @var boolean
*/
public $is_star;
/**
* When was the activity was created.
*
* @var timestamp
*/
public $created_date;
/**
* When was the activity (or closely related entity) was created or modified or deleted.
*
* @var timestamp
*/
public $modified_date;
/**
* Class constructor.
*/
......@@ -642,6 +654,38 @@ class CRM_Activity_DAO_Activity extends CRM_Core_DAO {
'bao' => 'CRM_Activity_BAO_Activity',
'localizable' => 0,
) ,
'activity_created_date' => array(
'name' => 'created_date',
'type' => CRM_Utils_Type::T_TIMESTAMP,
'title' => ts('Created Date') ,
'description' => 'When was the activity was created.',
'required' => false,
'export' => true,
'where' => 'civicrm_activity.created_date',
'headerPattern' => '',
'dataPattern' => '',
'default' => 'NULL',
'table_name' => 'civicrm_activity',
'entity' => 'Activity',
'bao' => 'CRM_Activity_BAO_Activity',
'localizable' => 0,
) ,
'activity_modified_date' => array(
'name' => 'modified_date',
'type' => CRM_Utils_Type::T_TIMESTAMP,
'title' => ts('Modified Date') ,
'description' => 'When was the activity (or closely related entity) was created or modified or deleted.',
'required' => false,
'export' => true,
'where' => 'civicrm_activity.modified_date',
'headerPattern' => '',
'dataPattern' => '',
'default' => 'CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP',
'table_name' => 'civicrm_activity',
'entity' => 'Activity',
'bao' => 'CRM_Activity_BAO_Activity',
'localizable' => 0,
) ,
);
CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'fields_callback', Civi::$statics[__CLASS__]['fields']);
}
......
......@@ -89,6 +89,10 @@ class CRM_Case_BAO_Case extends CRM_Case_DAO_Case {
* @return CRM_Case_BAO_Case
*/
public static function &create(&$params) {
// CRM-20958 - These fields are managed by MySQL triggers. Watch out for clients resaving stale timestamps.
unset($params['created_date']);
unset($params['modified_date']);
$transaction = new CRM_Core_Transaction();
if (!empty($params['id'])) {
......
......@@ -30,7 +30,7 @@
*
* Generated from xml/schema/CRM/Case/Case.xml
* DO NOT EDIT. Generated by CRM_Core_CodeGen
* (GenCodeChecksum:e45e7e2a53a945c4659cf393410a9d7a)
* (GenCodeChecksum:2a046fd795b19790f45c5d9dde06a538)
*/
require_once 'CRM/Core/DAO.php';
require_once 'CRM/Utils/Type.php';
......@@ -97,6 +97,18 @@ class CRM_Case_DAO_Case extends CRM_Core_DAO {
* @var boolean
*/
public $is_deleted;
/**
* When was the case was created.
*
* @var timestamp
*/
public $created_date;
/**
* When was the case (or closely related entity) was created or modified or deleted.
*
* @var timestamp
*/
public $modified_date;
/**
* Class constructor.
*/
......@@ -275,6 +287,38 @@ class CRM_Case_DAO_Case extends CRM_Core_DAO {
'bao' => 'CRM_Case_BAO_Case',
'localizable' => 0,
) ,
'case_created_date' => array(
'name' => 'created_date',
'type' => CRM_Utils_Type::T_TIMESTAMP,
'title' => ts('Created Date') ,
'description' => 'When was the case was created.',
'required' => false,
'export' => true,
'where' => 'civicrm_case.created_date',
'headerPattern' => '',
'dataPattern' => '',
'default' => 'NULL',
'table_name' => 'civicrm_case',
'entity' => 'Case',
'bao' => 'CRM_Case_BAO_Case',
'localizable' => 0,
) ,
'case_modified_date' => array(
'name' => 'modified_date',
'type' => CRM_Utils_Type::T_TIMESTAMP,
'title' => ts('Modified Date') ,
'description' => 'When was the case (or closely related entity) was created or modified or deleted.',
'required' => false,
'export' => true,
'where' => 'civicrm_case.modified_date',
'headerPattern' => '',
'dataPattern' => '',
'default' => 'CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP',
'table_name' => 'civicrm_case',
'entity' => 'Case',
'bao' => 'CRM_Case_BAO_Case',
'localizable' => 0,
) ,
);
CRM_Core_DAO_AllCoreTables::invoke(__CLASS__, 'fields_callback', Civi::$statics[__CLASS__]['fields']);
}
......
......@@ -3277,51 +3277,6 @@ LEFT JOIN civicrm_address add2 ON ( add1.master_id = add2.id )
}
}
/**
* Generate triggers to update the timestamp.
*
* The corresponding civicrm_contact row is updated on insert/update/delete
* to a table that extends civicrm_contact.
* Don't regenerate triggers for all such tables if only asked for one table.
*
* @param array $info
* Reference to the array where generated trigger information is being stored
* @param string|null $reqTableName
* Name of the table for which triggers are being generated, or NULL if all tables
* @param array $relatedTableNames
* Array of all core or all custom table names extending civicrm_contact
* @param string $contactRefColumn
* 'contact_id' if processing core tables, 'entity_id' if processing custom tables
*
* @link https://issues.civicrm.org/jira/browse/CRM-15602
* @see triggerInfo
*/
public static function generateTimestampTriggers(&$info, $reqTableName, $relatedTableNames, $contactRefColumn) {
// Safety
$contactRefColumn = CRM_Core_DAO::escapeString($contactRefColumn);
// If specific related table requested, just process that one
if (in_array($reqTableName, $relatedTableNames)) {
$relatedTableNames = array($reqTableName);
}
// If no specific table requested (include all related tables),
// or a specific related table requested (as matched above)
if (empty($reqTableName) || in_array($reqTableName, $relatedTableNames)) {
$info[] = array(
'table' => $relatedTableNames,
'when' => 'AFTER',
'event' => array('INSERT', 'UPDATE'),
'sql' => "\nUPDATE civicrm_contact SET modified_date = CURRENT_TIMESTAMP WHERE id = NEW.$contactRefColumn;\n",
);
$info[] = array(
'table' => $relatedTableNames,
'when' => 'AFTER',
'event' => array('DELETE'),
'sql' => "\nUPDATE civicrm_contact SET modified_date = CURRENT_TIMESTAMP WHERE id = OLD.$contactRefColumn;\n",
);
}
}
/**
* Get a list of triggers for the contact table.
*
......@@ -3343,37 +3298,17 @@ LEFT JOIN civicrm_address add2 ON ( add1.master_id = add2.id )
}
}
// Update timestamp for civicrm_contact itself
if ($tableName == NULL || $tableName == self::getTableName()) {
$info[] = array(
'table' => array(self::getTableName()),
'when' => 'BEFORE',
'event' => array('INSERT'),
'sql' => "\nSET NEW.created_date = CURRENT_TIMESTAMP;\n",
);
}
// Update timestamp when modifying closely related core tables
$relatedTables = array(
'civicrm_address',
'civicrm_email',
'civicrm_im',
'civicrm_phone',
'civicrm_website',
);
self::generateTimestampTriggers($info, $tableName, $relatedTables, 'contact_id');
// Update timestamp when modifying related custom-data tables
$customGroupTables = array();
$customGroupDAO = CRM_Core_BAO_CustomGroup::getAllCustomGroupsByBaseEntity('Contact');
$customGroupDAO->is_multiple = 0;
$customGroupDAO->find();
while ($customGroupDAO->fetch()) {
$customGroupTables[] = $customGroupDAO->table_name;
}
if (!empty($customGroupTables)) {
self::generateTimestampTriggers($info, $tableName, $customGroupTables, 'entity_id');
}
// Modifications to these records should update the contact timestamps.
\Civi\Core\SqlTrigger\TimestampTriggers::create('civicrm_contact', 'Contact')
->setRelations(array(
array('table' => 'civicrm_address', 'column' => 'contact_id'),
array('table' => 'civicrm_email', 'column' => 'contact_id'),
array('table' => 'civicrm_im', 'column' => 'contact_id'),
array('table' => 'civicrm_phone', 'column' => 'contact_id'),
array('table' => 'civicrm_website', 'column' => 'contact_id'),
)
)
->alterTriggerInfo($info, $tableName);
// Update phone table to populate phone_numeric field
if (!$tableName || $tableName == 'civicrm_phone') {
......
......@@ -418,6 +418,17 @@ class CRM_Upgrade_Incremental_php_FourSeven extends CRM_Upgrade_Incremental_Base
'civicrm_uf_group', 'cancel_button_text', "varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Custom Text to display on the cancel button when used in create or edit mode'", TRUE);
$this->addTask('Add Submit button text column to civicrm_uf_group', 'addColumn',
'civicrm_uf_group', 'submit_button_text', "varchar(64) COLLATE utf8_unicode_ci DEFAULT NULL COMMENT 'Custom Text to display on the submit button on profile edit/create screens'", TRUE);
$this->addTask('CRM-20958 - Add created_date to civicrm_activity', 'addColumn',
'civicrm_activity', 'created_date', "timestamp NULL DEFAULT NULL COMMENT 'When was the activity was created.'");
$this->addTask('CRM-20958 - Add modified_date to civicrm_activity', 'addColumn',
'civicrm_activity', 'modified_date', "timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'When was the activity (or closely related entity) was created or modified or deleted.'");
$this->addTask('CRM-20958 - Add created_date to civicrm_case', 'addColumn',
'civicrm_case', 'created_date', "timestamp NULL DEFAULT NULL COMMENT 'When was the case was created.'");
$this->addTask('CRM-20958 - Add modified_date to civicrm_case', 'addColumn',
'civicrm_case', 'modified_date', "timestamp NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 'When was the case (or closely related entity) was created or modified or deleted.'");
return TRUE;
}
......
......@@ -32,6 +32,8 @@
*/
class CRM_Utils_Check_Component_Case extends CRM_Utils_Check_Component {
const DOCTOR_WHEN = 'https://github.com/civicrm/org.civicrm.doctorwhen';
/**
* @var CRM_Case_XMLRepository
*/
......@@ -116,4 +118,48 @@ class CRM_Utils_Check_Component_Case extends CRM_Utils_Check_Component {
return $messages;
}
/**
* Check that the timestamp columns are populated. (CRM-20958)
*
* @return array<CRM_Utils_Check_Message>
* An empty array, or a list of warnings
*/
public function checkNullTimestamps() {
$messages = array();
$nullCount = 0;
$nullCount += CRM_Utils_SQL_Select::from('civicrm_activity')
->where('created_date IS NULL OR modified_date IS NULL')
->select('COUNT(*)')
->execute()
->fetchValue();
$nullCount += CRM_Utils_SQL_Select::from('civicrm_case')
->where('created_date IS NULL OR modified_date IS NULL')
->select('COUNT(*)')
->execute()
->fetchValue();
if ($nullCount > 0) {
$messages[] = new CRM_Utils_Check_Message(
__FUNCTION__,
'<p>' .
ts('The tables "<em>civicrm_activity</em>" and "<em>civicrm_case</em>" were updated to support two new fields, "<em>created_date</em>" and "<em>modified_date</em>". For historical data, these fields may appear blank. (%1 records have NULL timestamps.)', array(
1 => $nullCount,
)) .
'</p><p>' .
ts('At time of writing, this is not a problem. However, future extensions and improvements could rely on these fields, so it may be useful to back-fill them.') .
'</p><p>' .
ts('For further discussion, please visit %1', array(
1 => sprintf('<a href="%s" target="_blank">%s</a>', self::DOCTOR_WHEN, self::DOCTOR_WHEN),
)) .
'</p>',
ts('Timestamps for Activities and Cases'),
\Psr\Log\LogLevel::NOTICE,
'fa-clock-o'
);
}
return $messages;
}
}
......@@ -208,6 +208,39 @@ class Container {
->setFactory(array($class, 'singleton'));
}
$container->setDefinition('civi.activity.triggers', new Definition(
'Civi\Core\SqlTrigger\TimestampTriggers',
array('civicrm_activity', 'Activity')
))->addTag('kernel.event_listener', array('event' => 'hook_civicrm_triggerInfo', 'method' => 'onTriggerInfo'));
$container->setDefinition('civi.case.triggers', new Definition(
'Civi\Core\SqlTrigger\TimestampTriggers',
array('civicrm_case', 'Case')
))->addTag('kernel.event_listener', array('event' => 'hook_civicrm_triggerInfo', 'method' => 'onTriggerInfo'));
$container->setDefinition('civi.case.staticTriggers', new Definition(
'Civi\Core\SqlTrigger\StaticTriggers',
array(
array(
array(
'upgrade_check' => array('table' => 'civicrm_case', 'column' => 'modified_date'),
'table' => 'civicrm_case_activity',
'when' => 'AFTER',
'event' => array('INSERT'),
'sql' => "\nUPDATE civicrm_case SET modified_date = CURRENT_TIMESTAMP WHERE id = NEW.case_id;\n",
),
array(
'upgrade_check' => array('table' => 'civicrm_case', 'column' => 'modified_date'),
'table' => 'civicrm_activity',
'when' => 'BEFORE',
'event' => array('UPDATE', 'DELETE'),
'sql' => "\nUPDATE civicrm_case SET modified_date = CURRENT_TIMESTAMP WHERE id IN (SELECT ca.case_id FROM civicrm_case_activity ca WHERE ca.activity_id = OLD.id);\n",
),
),
)
))
->addTag('kernel.event_listener', array('event' => 'hook_civicrm_triggerInfo', 'method' => 'onTriggerInfo'));
$container->setDefinition('civi_token_compat', new Definition(
'Civi\Token\TokenCompatSubscriber',
array()
......
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
namespace Civi\Core\SqlTrigger;
/**
* Build a set of simple, literal SQL triggers.
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class StaticTriggers {
/**
* @var array
* A list of triggers, in the same format as hook_civicrm_triggerInfo.
* Additionally, you may specify `upgrade_check` to ensure that the trigger
* is *not* installed during early upgrade steps (before key dependencies are met).
*
* Ex: $triggers[0]['upgrade_check'] = array('table' => 'civicrm_case', 'column'=> 'modified_date');
*
* @see \CRM_Utils_Hook::triggerInfo
*/
private $triggers;
/**
* StaticTriggers constructor.
* @param $triggers
*/
public function __construct($triggers) {
$this->triggers = $triggers;
}
/**
* Add our list of triggers to the global list.
*
* @param \Civi\Core\Event\GenericHookEvent $e
* @see \CRM_Utils_Hook::triggerInfo
*/
public function onTriggerInfo($e) {
$this->alterTriggerInfo($e->info, $e->tableName);
}
/**
* Add our list of triggers to the global list.
*
* @see \CRM_Utils_Hook::triggerInfo
* @see \CRM_Core_DAO::triggerRebuild
*
* @param array $info
* See hook_civicrm_triggerInfo.
* @param string|NULL $tableFilter
* See hook_civicrm_triggerInfo.
*/
public function alterTriggerInfo(&$info, $tableFilter = NULL) {
foreach ($this->getTriggers() as $trigger) {
if ($tableFilter !== NULL) {
// Because sadism.
if (in_array($tableFilter, (array) $trigger['table'])) {
$trigger['table'] = $tableFilter;
}
}
if (\CRM_Core_Config::isUpgradeMode() && isset($trigger['upgrade_check'])) {
$uc = $trigger['upgrade_check'];
if (!\CRM_Core_DAO::checkFieldExists($uc['table'], $uc['column'])
) {
continue;
}
}
unset($trigger['upgrade_check']);
$info[] = $trigger;
}
}
/**
* @return mixed
*/
public function getTriggers() {
return $this->triggers;
}
/**
* @param mixed $triggers
* @return StaticTriggers
*/
public function setTriggers($triggers) {
$this->triggers = $triggers;
return $this;
}
/**
* @param $trigger
* @return StaticTriggers
*/
public function addTrigger($trigger) {
$this->triggers[] = $trigger;
return $this;
}
}
<?php
/*
+--------------------------------------------------------------------+
| CiviCRM version 4.7 |
+--------------------------------------------------------------------+
| Copyright CiviCRM LLC (c) 2004-2017 |
+--------------------------------------------------------------------+
| This file is a part of CiviCRM. |
| |
| CiviCRM is free software; you can copy, modify, and distribute it |
| under the terms of the GNU Affero General Public License |
| Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
| |
| CiviCRM is distributed in the hope that it will be useful, but |
| WITHOUT ANY WARRANTY; without even the implied warranty of |
| MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
| See the GNU Affero General Public License for more details. |
| |
| You should have received a copy of the GNU Affero General Public |
| License and the CiviCRM Licensing Exception along |
| with this program; if not, contact CiviCRM LLC |
| at info[AT]civicrm[DOT]org. If you have questions about the |
| GNU Affero General Public License or the licensing of CiviCRM, |
| see the CiviCRM license FAQ at http://civicrm.org/licensing |
+--------------------------------------------------------------------+
*/
namespace Civi\Core\SqlTrigger;
use Civi\Core\Event\GenericHookEvent;
/**
* Build a set of SQL triggers for tracking timestamps on an entity.
*
* This class is a generalization of CRM-10554 with the aim of enabling CRM-20958.
*
* @package CRM
* @copyright CiviCRM LLC (c) 2004-2017
*/
class TimestampTriggers {
/**
* @var string
* SQL table name.
* Ex: 'civicrm_contact', 'civicrm_activity'.
*/
private $tableName;
/**
* @var string
* An entity name (from civicrm_custom_group.extends).
* Ex: 'Contact', 'Activity'.
*/
private $customDataEntity;
/**
* @var string
* SQL column name.
* Ex: 'created_date'.
*/
private $createdDate;
/**
* @var string
* SQL column name.
* Ex: 'modified_date'.
*/
private $modifiedDate;
/**
* @var array
* Ex: $relations[0] == array('table' => 'civicrm_bar', 'column' => 'foo_id');
*/
private $relations;
/**
* @param string $tableName
* SQL table name.
* Ex: 'civicrm_contact', 'civicrm_activity'.
* @param string $customDataEntity
* An entity name (from civicrm_custom_group.extends).
* Ex: 'Contact', 'Activity'.
* @return TimestampTriggers
*/
public static function create($tableName, $customDataEntity) {
return new static($tableName, $customDataEntity);
}
/**
* TimestampTriggers constructor.
*
* @param string $tableName
* SQL table name.
* Ex: 'civicrm_contact', 'civicrm_activity'.
* @param string $customDataEntity
* An entity name (from civicrm_custom_group.extends).
* Ex: 'Contact', 'Activity'.
* @param string $createdDate
* SQL column name.
* Ex: 'created_date'.
* @param string $modifiedDate
* SQL column name.
* Ex: 'modified_date'.
* @param array $relations
* Ex: $relations[0] == array('table' => 'civicrm_bar', 'column' => 'foo_id');
*/
public function __construct(
$tableName,
$customDataEntity,
$createdDate = 'created_date',
$modifiedDate = 'modified_date',
$relations = array()
) {
$this->tableName = $tableName;
$this->customDataEntity = $customDataEntity;
$this->createdDate = $createdDate;
$this->modifiedDate = $modifiedDate;
$this->relations = $relations;
}
/**
* Add our list of triggers to the global list.
*
* @param \Civi\Core\Event\GenericHookEvent $e
* @see \CRM_Utils_Hook::triggerInfo
*/
public function onTriggerInfo($e) {
$this->alterTriggerInfo($e->info, $e->tableName);
}
/**
* Add our list of triggers to the global list.
*
* @see \CRM_Utils_Hook::triggerInfo
* @see \CRM_Core_DAO::triggerRebuild
*
* @param array $info
* See hook_civicrm_triggerInfo.
* @param string|NULL $tableFilter
* See hook_civicrm_triggerInfo.
*/
public function alterTriggerInfo(&$info, $tableFilter = NULL) {
// If we haven't upgraded yet, then the created_date/modified_date may not exist.
// In the past, this was a version-based check, but checkFieldExists()
// seems more robust.
if (\CRM_Core_Config::isUpgradeMode()) {
if (!\CRM_Core_DAO::checkFieldExists($this->getTableName(),
$this->getCreatedDate())
) {
return;
}
}
if ($tableFilter == NULL || $tableFilter == $this->getTableName()) {
$info[] = array(
'table' => array($this->getTableName()),
'when' => 'BEFORE',
'event' => array('INSERT'),
'sql' => "\nSET NEW.{$this->getCreatedDate()} = CURRENT_TIMESTAMP;\n",
);
}
// Update timestamp when modifying closely related tables
$relIdx = \CRM_Utils_Array::index(
array('column', 'table'),
$this->getAllRelations()
);
foreach ($relIdx as $column => $someRelations) {
$this->generateTimestampTriggers($info, $tableFilter,
array_keys($someRelations), $column);
}
}
/**
* Generate triggers to update the timestamp.
*
* The corresponding civicrm_FOO row is updated on insert/update/delete
* to a table that extends civicrm_FOO.
* Don't regenerate triggers for all such tables if only asked for one table.
*
* @param array $info
* Reference to the array where generated trigger information is being stored
* @param string|null $tableFilter
* Name of the table for which triggers are being generated, or NULL if all tables
* @param array $relatedTableNames
* Array of all core or all custom table names extending civicrm_FOO
* @param string $contactRefColumn
* 'contact_id' if processing core tables, 'entity_id' if processing custom tables
*
* @link https://issues.civicrm.org/jira/browse/CRM-15602
* @see triggerInfo
*/
public function generateTimestampTriggers(
&$info,
$tableFilter,
$relatedTableNames,
$contactRefColumn
) {
// Safety
$contactRefColumn = \CRM_Core_DAO::escapeString($contactRefColumn);
// If specific related table requested, just process that one.
// (Reply: This feels fishy.)
if (in_array($tableFilter, $relatedTableNames)) {
$relatedTableNames = array($tableFilter);
}
// If no specific table requested (include all related tables),
// or a specific related table requested (as matched above)
if (empty($tableFilter) || isset($relatedTableNames[$tableFilter])) {
$info[] = array(
'table' => $relatedTableNames,
'when' => 'AFTER',
'event' => array('INSERT', 'UPDATE'),
'sql' => "\nUPDATE {$this->getTableName()} SET {$this->getModifiedDate()} = CURRENT_TIMESTAMP WHERE id = NEW.$contactRefColumn;\n",