INFRA-132 - CRM/Core - Misc
[civicrm-core.git] / CRM / Core / DAO.php
index 489c068a5614d52b453b1dddc14ef389a19699bb..2b686b3ecc67af2396b8658d8c65db88889d2b9d 100644 (file)
@@ -1,7 +1,7 @@
 <?php
 /*
   +--------------------------------------------------------------------+
-  | CiviCRM version 4.5                                                |
+  | CiviCRM version 4.6                                                |
   +--------------------------------------------------------------------+
   | Copyright CiviCRM LLC (c) 2004-2014                                |
   +--------------------------------------------------------------------+
@@ -45,13 +45,13 @@ require_once 'CRM/Core/I18n.php';
 class CRM_Core_DAO extends DB_DataObject {
 
   /**
-   * a null object so we can pass it as reference if / when needed
+   * A null object so we can pass it as reference if / when needed
    */
   static $_nullObject = NULL;
   static $_nullArray = array();
 
   static $_dbColumnValueCache = NULL;
-  CONST NOT_NULL = 1, IS_NULL = 2,
+  const NOT_NULL = 1, IS_NULL = 2,
   DB_DAO_NOTNULL = 128,
   VALUE_SEPARATOR = "\ 1",
   BULK_INSERT_COUNT = 200,
@@ -69,7 +69,7 @@ class CRM_Core_DAO extends DB_DataObject {
    */
   static $_testEntitiesToSkip = array();
   /**
-   * the factory class for this application
+   * The factory class for this application
    * @var object
    */
   static $_factory = NULL;
@@ -82,28 +82,28 @@ class CRM_Core_DAO extends DB_DataObject {
    * @return \CRM_Core_DAO
   @access public
    */
-  function __construct() {
+  public function __construct() {
     $this->initialize();
     $this->__table = $this->getTableName();
   }
 
   /**
-   * empty definition for virtual function
+   * Empty definition for virtual function
    */
-  static function getTableName() {
+  public static function getTableName() {
     return NULL;
   }
 
   /**
-   * initialize the DAO object
+   * Initialize the DAO object
    *
-   * @param string $dsn   the database connection string
+   * @param string $dsn
+   *   The database connection string.
    *
    * @return void
-   * @access private
    * @static
    */
-  static function init($dsn) {
+  public static function init($dsn) {
     $options = &PEAR::getStaticProperty('DB_DataObject', 'options');
     $options['database'] = $dsn;
     if (defined('CIVICRM_DAO_DEBUG')) {
@@ -112,9 +112,9 @@ class CRM_Core_DAO extends DB_DataObject {
   }
 
   /**
-   * @param $fieldName
+   * @param string $fieldName
    * @param $fieldDef
-   * @param $params
+   * @param array $params
    *
    */
   protected function assignTestFK($fieldName, $fieldDef, $params) {
@@ -163,7 +163,8 @@ class CRM_Core_DAO extends DB_DataObject {
    *
    * @param string $fieldName
    * @param array $fieldDef
-   * @param int $counter the globally-unique ID of the test object
+   * @param int $counter
+   *   The globally-unique ID of the test object.
    */
   protected function assignTestValue($fieldName, &$fieldDef, $counter) {
     $dbName = $fieldDef['name'];
@@ -268,15 +269,14 @@ class CRM_Core_DAO extends DB_DataObject {
   }
 
   /**
-   * reset the DAO object. DAO is kinda crappy in that there is an unwritten
+   * Reset the DAO object. DAO is kinda crappy in that there is an unwritten
    * rule of one query per DAO. We attempt to get around this crappy restricrion
    * by resetting some of DAO's internal fields. Use this with caution
    *
    * @return void
-   * @access public
    *
    */
-  function reset() {
+  public function reset() {
 
     foreach (array_keys($this->table()) as $field) {
       unset($this->$field);
@@ -292,11 +292,11 @@ class CRM_Core_DAO extends DB_DataObject {
   }
 
   /**
-   * @param $tableName
+   * @param string $tableName
    *
    * @return string
    */
-  static function getLocaleTableName($tableName) {
+  public static function getLocaleTableName($tableName) {
     global $dbLocale;
     if ($dbLocale) {
       $tables = CRM_Core_I18n_Schema::schemaStructureTables();
@@ -310,12 +310,14 @@ class CRM_Core_DAO extends DB_DataObject {
   /**
    * Execute a query by the current DAO, localizing it along the way (if needed).
    *
-   * @param string $query        the SQL query for execution
-   * @param bool   $i18nRewrite  whether to rewrite the query
+   * @param string $query
+   *   The SQL query for execution.
+   * @param bool $i18nRewrite
+   *   Whether to rewrite the query.
    *
    * @return object              the current DAO object after the query execution
    */
-  function query($query, $i18nRewrite = TRUE) {
+  public function query($query, $i18nRewrite = TRUE) {
     // rewrite queries that should use $dbLocale-based views for multi-language installs
     global $dbLocale;
     if ($i18nRewrite and $dbLocale) {
@@ -328,13 +330,13 @@ class CRM_Core_DAO extends DB_DataObject {
   /**
    * Static function to set the factory instance for this class.
    *
-   * @param object $factory  the factory application object
+   * @param object $factory
+   *   The factory application object.
    *
    * @return void
-   * @access public
    * @static
    */
-  static function setFactory(&$factory) {
+  public static function setFactory(&$factory) {
     self::$_factory = &$factory;
   }
 
@@ -344,9 +346,8 @@ class CRM_Core_DAO extends DB_DataObject {
    * @param string $table
    *
    * @return void
-   * @access public
    */
-  function factory($table = '') {
+  public function factory($table = '') {
     if (!isset(self::$_factory)) {
       return parent::factory($table);
     }
@@ -359,9 +360,8 @@ class CRM_Core_DAO extends DB_DataObject {
    * we need to set the links manually.
    *
    * @return void
-   * @access protected
    */
-  function initialize() {
+  public function initialize() {
     $this->_connect();
     $this->query("SET NAMES utf8");
   }
@@ -369,11 +369,10 @@ class CRM_Core_DAO extends DB_DataObject {
   /**
    * Defines the default key as 'id'.
    *
-   * @access protected
    *
    * @return array
    */
-  function keys() {
+  public function keys() {
     static $keys;
     if (!isset($keys)) {
       $keys = array('id');
@@ -385,11 +384,10 @@ class CRM_Core_DAO extends DB_DataObject {
    * Tells DB_DataObject which keys use autoincrement.
    * 'id' is autoincrementing by default.
    *
-   * @access protected
    *
    * @return array
    */
-  function sequenceKey() {
+  public function sequenceKey() {
     static $sequenceKeys;
     if (!isset($sequenceKeys)) {
       $sequenceKeys = array('id', TRUE);
@@ -398,21 +396,19 @@ class CRM_Core_DAO extends DB_DataObject {
   }
 
   /**
-   * returns list of FK relationships
+   * Returns list of FK relationships
    *
    * @static
-   * @access public
    *
    * @return array of CRM_Core_Reference_Interface
    */
-  static function getReferenceColumns() {
+  public static function getReferenceColumns() {
     return array();
   }
 
   /**
-   * returns all the column names of this table
+   * Returns all the column names of this table
    *
-   * @access public
    *
    * @return array
    */
@@ -422,13 +418,12 @@ class CRM_Core_DAO extends DB_DataObject {
   }
 
   /**
-   * get/set an associative array of table columns
+   * Get/set an associative array of table columns
    *
-   * @access public
-   * @param  array key=>type array
+   * @param array key=>type array
    * @return array (associative)
    */
-  function table() {
+  public function table() {
     $fields = &$this->fields();
 
     $table = array();
@@ -447,12 +442,18 @@ class CRM_Core_DAO extends DB_DataObject {
   /**
    * @return $this
    */
-  function save() {
+  public function save() {
     if (!empty($this->id)) {
       $this->update();
+
+      $event = new \Civi\Core\DAO\Event\PostUpdate($this);
+      \Civi\Core\Container::singleton()->get('dispatcher')->dispatch("DAO::post-update", $event);
     }
     else {
       $this->insert();
+
+      $event = new \Civi\Core\DAO\Event\PostUpdate($this);
+      \Civi\Core\Container::singleton()->get('dispatcher')->dispatch("DAO::post-insert", $event);
     }
     $this->free();
 
@@ -461,10 +462,19 @@ class CRM_Core_DAO extends DB_DataObject {
     return $this;
   }
 
+  public function delete($useWhere = FALSE) {
+    $result = parent::delete($useWhere);
+
+    $event = new \Civi\Core\DAO\Event\PostDelete($this, $result);
+    \Civi\Core\Container::singleton()->get('dispatcher')->dispatch("DAO::post-delete", $event);
+
+    return $result;
+  }
+
   /**
    * @param bool $created
    */
-  function log($created = FALSE) {
+  public function log($created = FALSE) {
     static $cid = NULL;
 
     if (!$this->getLog()) {
@@ -493,12 +503,12 @@ class CRM_Core_DAO extends DB_DataObject {
    * Given an associative array of name/value pairs, extract all the values
    * that belong to this object and initialize the object with said values
    *
-   * @param array $params (reference ) associative array of name/value pairs
+   * @param array $params
+   *   (reference ) associative array of name/value pairs.
    *
    * @return boolean      did we copy all null values into the object
-   * @access public
    */
-  function copyValues(&$params) {
+  public function copyValues(&$params) {
     $fields = &$this->fields();
     $allNull = TRUE;
     foreach ($fields as $name => $value) {
@@ -534,14 +544,15 @@ class CRM_Core_DAO extends DB_DataObject {
    * this is a destructive store, calling function is responsible
    * for keeping sanity of id's.
    *
-   * @param object $object the object that we are extracting data from
-   * @param array  $values (reference ) associative array of name/value pairs
+   * @param object $object
+   *   The object that we are extracting data from.
+   * @param array $values
+   *   (reference ) associative array of name/value pairs.
    *
    * @return void
-   * @access public
    * @static
    */
-  static function storeValues(&$object, &$values) {
+  public static function storeValues(&$object, &$values) {
     $fields = &$object->fields();
     foreach ($fields as $name => $value) {
       $dbName = $value['name'];
@@ -555,15 +566,15 @@ class CRM_Core_DAO extends DB_DataObject {
   }
 
   /**
-   * create an attribute for this specific field. We only do this for strings and text
+   * Create an attribute for this specific field. We only do this for strings and text
    *
-   * @param array $field the field under task
+   * @param array $field
+   *   The field under task.
    *
    * @return array|null the attributes for the object
-   * @access public
    * @static
    */
-  static function makeAttribute($field) {
+  public static function makeAttribute($field) {
     if ($field) {
       if (CRM_Utils_Array::value('type', $field) == CRM_Utils_Type::T_STRING) {
         $maxLength = CRM_Utils_Array::value('maxlength', $field);
@@ -607,15 +618,16 @@ class CRM_Core_DAO extends DB_DataObject {
    * Get the size and maxLength attributes for this text field
    * (or for all text fields) in the DAO object.
    *
-   * @param string $class     name of DAO class
-   * @param string $fieldName field that i'm interested in or null if
+   * @param string $class
+   *   Name of DAO class.
+   * @param string $fieldName
+   *   Field that i'm interested in or null if.
    *                          you want the attributes for all DAO text fields
    *
    * @return array assoc array of name => attribute pairs
-   * @access public
    * @static
    */
-  static function getAttribute($class, $fieldName = NULL) {
+  public static function getAttribute($class, $fieldName = NULL) {
     $object = new $class( );
     $fields = &$object->fields();
     if ($fieldName != NULL) {
@@ -643,24 +655,27 @@ class CRM_Core_DAO extends DB_DataObject {
    *
    * @throws Exception
    */
-  static function transaction($type) {
+  public static function transaction($type) {
     CRM_Core_Error::fatal('This function is obsolete, please use CRM_Core_Transaction');
   }
 
   /**
    * Check if there is a record with the same name in the db
    *
-   * @param string $value     the value of the field we are checking
-   * @param string $daoName   the dao object name
-   * @param string $daoID     the id of the object being updated. u can change your name
+   * @param string $value
+   *   The value of the field we are checking.
+   * @param string $daoName
+   *   The dao object name.
+   * @param string $daoID
+   *   The id of the object being updated. u can change your name.
    *                          as long as there is no conflict
-   * @param string $fieldName the name of the field in the DAO
+   * @param string $fieldName
+   *   The name of the field in the DAO.
    *
    * @return boolean     true if object exists
-   * @access public
    * @static
    */
-  static function objectExists($value, $daoName, $daoID, $fieldName = 'name') {
+  public static function objectExists($value, $daoName, $daoID, $fieldName = 'name') {
     $object = new $daoName( );
     $object->$fieldName = $value;
 
@@ -679,12 +694,13 @@ class CRM_Core_DAO extends DB_DataObject {
    *
    * @param string $tableName
    * @param string $columnName
-   * @param bool   $i18nRewrite  whether to rewrite the query on multilingual setups
+   * @param bool $i18nRewrite
+   *   Whether to rewrite the query on multilingual setups.
    *
    * @return boolean true if exists, else false
    * @static
    */
-  static function checkFieldExists($tableName, $columnName, $i18nRewrite = TRUE) {
+  public static function checkFieldExists($tableName, $columnName, $i18nRewrite = TRUE) {
     $query = "
 SHOW COLUMNS
 FROM $tableName
@@ -710,7 +726,7 @@ LIKE %1
    * @return array
    * @static
    */
-  static function getStorageValues($tableName = NULL, $maxTablesToCheck = 10, $fieldName = 'Engine') {
+  public static function getStorageValues($tableName = NULL, $maxTablesToCheck = 10, $fieldName = 'Engine') {
     $values = array();
     $query = "SHOW TABLE STATUS LIKE %1";
 
@@ -751,7 +767,7 @@ LIKE %1
    *
    * @return bool
    */
-  static function isDBMyISAM($maxTablesToCheck = 10) {
+  public static function isDBMyISAM($maxTablesToCheck = 10) {
     // show error if any of the tables, use 'MyISAM' storage engine.
     $engines = self::getStorageValues(NULL, $maxTablesToCheck);
     if (array_key_exists('MyISAM', $engines)) {
@@ -769,7 +785,7 @@ LIKE %1
    * @return boolean true if constraint exists, false otherwise
    * @static
    */
-  static function checkConstraintExists($tableName, $constraint) {
+  public static function checkConstraintExists($tableName, $constraint) {
     static $show = array();
 
     if (!array_key_exists($tableName, $show)) {
@@ -793,11 +809,10 @@ LIKE %1
    * @param array $tables
    *
    * @throws Exception
-   * @internal param string $tableName
    *
    * @return boolean true if CONSTRAINT keyword exists, false otherwise
    */
-  static function schemaRequiresRebuilding($tables = array("civicrm_contact")) {
+  public static function schemaRequiresRebuilding($tables = array("civicrm_contact")) {
     $show = array();
     foreach($tables as $tableName){
       if (!array_key_exists($tableName, $show)) {
@@ -813,10 +828,10 @@ LIKE %1
       }
 
       $result = preg_match("/\bCONSTRAINT\b\s/i", $show[$tableName]) ? TRUE : FALSE;
-      if($result == TRUE){
+      if ($result == TRUE){
         continue;
       }
-      else{
+      else {
         return FALSE;
       }
     }
@@ -833,7 +848,7 @@ LIKE %1
    * @return boolean true if in format, false otherwise
    * @static
    */
-  static function checkFKConstraintInFormat($tableName, $columnName) {
+  public static function checkFKConstraintInFormat($tableName, $columnName) {
     static $show = array();
 
     if (!array_key_exists($tableName, $show)) {
@@ -862,7 +877,7 @@ LIKE %1
    * @return boolean true if the value is always $columnValue, false otherwise
    * @static
    */
-  static function checkFieldHasAlwaysValue($tableName, $columnName, $columnValue) {
+  public static function checkFieldHasAlwaysValue($tableName, $columnName, $columnValue) {
     $query  = "SELECT * FROM $tableName WHERE $columnName != '$columnValue'";
     $dao    = CRM_Core_DAO::executeQuery($query);
     $result = $dao->fetch() ? FALSE : TRUE;
@@ -879,7 +894,7 @@ LIKE %1
    * @return boolean true if if the value is always NULL, false otherwise
    * @static
    */
-  static function checkFieldIsAlwaysNull($tableName, $columnName) {
+  public static function checkFieldIsAlwaysNull($tableName, $columnName) {
     $query  = "SELECT * FROM $tableName WHERE $columnName IS NOT NULL";
     $dao    = CRM_Core_DAO::executeQuery($query);
     $result = $dao->fetch() ? FALSE : TRUE;
@@ -895,7 +910,7 @@ LIKE %1
    * @return boolean true if exists, else false
    * @static
    */
-  static function checkTableExists($tableName) {
+  public static function checkTableExists($tableName) {
     $query = "
 SHOW TABLES
 LIKE %1
@@ -913,7 +928,7 @@ LIKE %1
    *
    * @return bool
    */
-  function checkVersion($version) {
+  public function checkVersion($version) {
     $query = "
 SELECT version
 FROM   civicrm_domain
@@ -922,20 +937,41 @@ FROM   civicrm_domain
     return trim($version) == trim($dbVersion) ? TRUE : FALSE;
   }
 
+  /**
+   * Find a DAO object for the given ID and return it.
+   *
+   * @param int $id
+   *   Id of the DAO object being searched for.
+   *
+   * @return object Object of the type of the class that called this function.
+   */
+  public static function findById($id) {
+    $object = new static();
+    $object->id = $id;
+    if (!$object->find(TRUE)) {
+      throw new Exception("Unable to find a " . get_called_class() . " with id {$id}.");
+    }
+    return $object;
+  }
+
   /**
    * Given a DAO name, a column name and a column value, find the record and GET the value of another column in that record
    *
-   * @param string  $daoName       Name of the DAO (Example: CRM_Contact_DAO_Contact to retrieve value from a contact)
-   * @param int     $searchValue   Value of the column you want to search by
-   * @param string  $returnColumn  Name of the column you want to GET the value of
-   * @param string  $searchColumn  Name of the column you want to search by
-   * @param boolean $force         Skip use of the cache
+   * @param string $daoName
+   *   Name of the DAO (Example: CRM_Contact_DAO_Contact to retrieve value from a contact).
+   * @param int $searchValue
+   *   Value of the column you want to search by.
+   * @param string $returnColumn
+   *   Name of the column you want to GET the value of.
+   * @param string $searchColumn
+   *   Name of the column you want to search by.
+   * @param bool $force
+   *   Skip use of the cache.
    *
    * @return string|null          Value of $returnColumn in the retrieved record
    * @static
-   * @access public
    */
-  static function getFieldValue($daoName, $searchValue, $returnColumn = 'name', $searchColumn = 'id', $force = FALSE) {
+  public static function getFieldValue($daoName, $searchValue, $returnColumn = 'name', $searchColumn = 'id', $force = FALSE) {
     if (
       empty($searchValue) ||
       trim(strtolower($searchValue)) == 'null'
@@ -971,17 +1007,21 @@ FROM   civicrm_domain
   /**
    * Given a DAO name, a column name and a column value, find the record and SET the value of another column in that record
    *
-   * @param string $daoName       Name of the DAO (Example: CRM_Contact_DAO_Contact to retrieve value from a contact)
-   * @param int    $searchValue   Value of the column you want to search by
-   * @param string $setColumn     Name of the column you want to SET the value of
-   * @param string $setValue      SET the setColumn to this value
-   * @param string $searchColumn  Name of the column you want to search by
+   * @param string $daoName
+   *   Name of the DAO (Example: CRM_Contact_DAO_Contact to retrieve value from a contact).
+   * @param int $searchValue
+   *   Value of the column you want to search by.
+   * @param string $setColumn
+   *   Name of the column you want to SET the value of.
+   * @param string $setValue
+   *   SET the setColumn to this value.
+   * @param string $searchColumn
+   *   Name of the column you want to search by.
    *
    * @return boolean          true if we found and updated the object, else false
    * @static
-   * @access public
    */
-  static function setFieldValue($daoName, $searchValue, $setColumn, $setValue, $searchColumn = 'id') {
+  public static function setFieldValue($daoName, $searchValue, $setColumn, $setValue, $searchColumn = 'id') {
     $object = new $daoName( );
     $object->selectAdd();
     $object->selectAdd("$searchColumn, $setColumn");
@@ -1001,13 +1041,13 @@ FROM   civicrm_domain
    * Get sort string
    *
    * @param array|object $sort either array or CRM_Utils_Sort
-   * @param string $default - default sort value
+   * @param string $default
+   *   Default sort value.
    *
    * @return string - sortString
-   * @access public
    * @static
    */
-  static function getSortString($sort, $default = NULL) {
+  public static function getSortString($sort, $default = NULL) {
     // check if sort is of type CRM_Utils_Sort
     if (is_a($sort, 'CRM_Utils_Sort')) {
       return $sort->orderBy();
@@ -1024,22 +1064,21 @@ FROM   civicrm_domain
   }
 
   /**
-   * Takes a bunch of params that are needed to match certain criteria and
-   * retrieves the relevant objects. Typically the valid params are only
-   * contact_id. We'll tweak this function to be more full featured over a period
-   * of time. This is the inverse function of create. It also stores all the retrieved
-   * values in the default array
+   * Fetch object based on array of properties
    *
-   * @param string $daoName  name of the dao object
-   * @param array  $params   (reference ) an assoc array of name/value pairs
-   * @param array  $defaults (reference ) an assoc array to hold the flattened values
-   * @param array  $returnProperities     an assoc array of fields that need to be returned, eg array( 'first_name', 'last_name')
+   * @param string $daoName
+   *   Name of the dao object.
+   * @param array $params
+   *   (reference ) an assoc array of name/value pairs.
+   * @param array $defaults
+   *   (reference ) an assoc array to hold the flattened values.
+   * @param array $returnProperities
+   *   An assoc array of fields that need to be returned, eg array( 'first_name', 'last_name').
    *
    * @return object an object of type referenced by daoName
-   * @access public
    * @static
    */
-  static function commonRetrieve($daoName, &$params, &$defaults, $returnProperities = NULL) {
+  public static function commonRetrieve($daoName, &$params, &$defaults, $returnProperities = NULL) {
     $object = new $daoName( );
     $object->copyValues($params);
 
@@ -1059,14 +1098,15 @@ FROM   civicrm_domain
   /**
    * Delete the object records that are associated with this contact
    *
-   * @param string $daoName  name of the dao object
-   * @param  int  $contactId id of the contact to delete
+   * @param string $daoName
+   *   Name of the dao object.
+   * @param int $contactId
+   *   Id of the contact to delete.
    *
    * @return void
-   * @access public
    * @static
    */
-  static function deleteEntityContact($daoName, $contactId) {
+  public static function deleteEntityContact($daoName, $contactId) {
     $object = new $daoName( );
 
     $object->entity_table = 'civicrm_contact';
@@ -1075,9 +1115,10 @@ FROM   civicrm_domain
   }
 
   /**
-   * execute a query
+   * Execute a query
    *
-   * @param string $query query to be executed
+   * @param string $query
+   *   Query to be executed.
    *
    * @param array $params
    * @param bool $abort
@@ -1086,9 +1127,8 @@ FROM   civicrm_domain
    * @param bool $i18nRewrite
    * @param bool $trapException
    *
-   * @return Object CRM_Core_DAO object that holds the results of the query
+   * @return CRM_Core_DAO object that holds the results of the query
    * @static
-   * @access public
    */
   static function &executeQuery(
     $query,
@@ -1100,7 +1140,6 @@ FROM   civicrm_domain
     $trapException = FALSE
   ) {
     $queryStr = self::composeQuery($query, $params, $abort);
-    //CRM_Core_Error::debug( 'q', $queryStr );
 
     if (!$daoName) {
       $dao = new CRM_Core_DAO();
@@ -1130,18 +1169,19 @@ FROM   civicrm_domain
   }
 
   /**
-   * execute a query and get the single result
+   * Execute a query and get the single result
    *
-   * @param string $query query to be executed
+   * @param string $query
+   *   Query to be executed.
    * @param array $params
    * @param bool $abort
    * @param bool $i18nRewrite
    * @return string|null the result of the query if any
    *
    * @static
-   * @access public
    */
-  static function &singleValueQuery($query,
+  static function &singleValueQuery(
+    $query,
     $params      = array(),
     $abort       = TRUE,
     $i18nRewrite = TRUE
@@ -1170,13 +1210,13 @@ FROM   civicrm_domain
 
   /**
    * @param $query
-   * @param $params
+   * @param array $params
    * @param bool $abort
    *
    * @return string
    * @throws Exception
    */
-  static function composeQuery($query, &$params, $abort = TRUE) {
+  public static function composeQuery($query, &$params, $abort = TRUE) {
     $tr = array();
     foreach ($params as $key => $item) {
       if (is_numeric($key)) {
@@ -1223,18 +1263,9 @@ FROM   civicrm_domain
   /**
    * @param null $ids
    */
-  static function freeResult($ids = NULL) {
+  public static function freeResult($ids = NULL) {
     global $_DB_DATAOBJECT;
 
-    /***
-     $q = array( );
-     foreach ( array_keys( $_DB_DATAOBJECT['RESULTS'] ) as $id ) {
-     $q[] = $_DB_DATAOBJECT['RESULTS'][$id]->query;
-     }
-     CRM_Core_Error::debug( 'k', $q );
-     return;
-     ***/
-
     if (!$ids) {
       if (!$_DB_DATAOBJECT ||
         !isset($_DB_DATAOBJECT['RESULTS'])
@@ -1262,18 +1293,22 @@ FROM   civicrm_domain
    * This function is to make a shallow copy of an object
    * and all the fields in the object
    *
-   * @param string $daoName                 name of the dao
-   * @param array  $criteria                array of all the fields & values
+   * @param string $daoName
+   *   Name of the dao.
+   * @param array $criteria
+   *   Array of all the fields & values.
    *                                        on which basis to copy
-   * @param array  $newData                 array of all the fields & values
+   * @param array $newData
+   *   Array of all the fields & values.
    *                                        to be copied besides the other fields
-   * @param string $fieldsFix               array of fields that you want to prefix/suffix/replace
-   * @param string $blockCopyOfDependencies fields that you want to block from
+   * @param string $fieldsFix
+   *   Array of fields that you want to prefix/suffix/replace.
+   * @param string $blockCopyOfDependencies
+   *   Fields that you want to block from.
    *                                        getting copied
    *
    *
    * @return (reference )                   the newly created copy of the object
-   * @access public
    */
   static function &copyGeneric($daoName, $criteria, $newData = NULL, $fieldsFix = NULL, $blockCopyOfDependencies = NULL) {
     $object = new $daoName( );
@@ -1348,12 +1383,47 @@ FROM   civicrm_domain
     return $newObject;
   }
 
+  public static function cascadeUpdate($daoName, $fromId, $toId, $newData = array()) {
+    $object = new $daoName( );
+    $object->id = $fromId;
+
+    if ($object->find(TRUE)) {
+      $newObject = new $daoName( );
+      $newObject->id = $toId;
+
+      if ($newObject->find(TRUE)) {
+        $fields = &$object->fields();
+        foreach ($fields as $name => $value) {
+          if ($name == 'id' || $value['name'] == 'id') {
+            // copy everything but the id!
+            continue;
+          }
+
+          $colName = $value['name'];
+          $newObject->$colName = $object->$colName;
+
+          if (substr($name, -5) == '_date' ||
+            substr($name, -10) == '_date_time'
+          ) {
+            $newObject->$colName = CRM_Utils_Date::isoToMysql($newObject->$colName);
+          }
+        }
+        foreach ($newData as $k => $v) {
+          $newObject->$k = $v;
+        }
+        $newObject->save();
+        return $newObject;
+      }
+    }
+    return CRM_Core_DAO::$_nullObject;
+  }
+
   /**
    * Given the component id, compute the contact id
    * since its used for things like send email
    *
    * @param $componentIDs
-   * @param $tableName
+   * @param string $tableName
    *
    * @return array
    */
@@ -1379,25 +1449,20 @@ SELECT contact_id
   }
 
   /**
-   * Takes a bunch of params that are needed to match certain criteria and
-   * retrieves the relevant objects. Typically the valid params are only
-   * contact_id. We'll tweak this function to be more full featured over a period
-   * of time. This is the inverse function of create. It also stores all the retrieved
-   * values in the default array
+   * Fetch object based on array of properties
    *
-   * @param string $daoName name of the dao object
+   * @param string $daoName
+   *   Name of the dao object.
    * @param string $fieldIdName
-   * @param $fieldId
+   * @param int $fieldId
    * @param $details
-   * @param array $returnProperities an assoc array of fields that need to be returned, eg array( 'first_name', 'last_name')
+   * @param array $returnProperities
+   *   An assoc array of fields that need to be returned, eg array( 'first_name', 'last_name').
    *
-   * @internal param array $params (reference ) an assoc array of name/value pairs
-   * @internal param array $defaults (reference ) an assoc array to hold the flattened values
    * @return object an object of type referenced by daoName
-   * @access public
    * @static
    */
-  static function commonRetrieveAll($daoName, $fieldIdName = 'id', $fieldId, &$details, $returnProperities = NULL) {
+  public static function commonRetrieveAll($daoName, $fieldIdName = 'id', $fieldId, &$details, $returnProperities = NULL) {
     require_once (str_replace('_', DIRECTORY_SEPARATOR, $daoName) . ".php");
     $object = new $daoName( );
     $object->$fieldIdName = $fieldId;
@@ -1419,7 +1484,7 @@ SELECT contact_id
     return $details;
   }
 
-  static function dropAllTables() {
+  public static function dropAllTables() {
 
     // first drop all the custom tables we've created
     CRM_Core_BAO_CustomGroup::dropAllTables();
@@ -1441,10 +1506,24 @@ SELECT contact_id
    *
    * @return string
    */
-  static function escapeString($string) {
+  public static function escapeString($string) {
     static $_dao = NULL;
 
     if (!$_dao) {
+      // If this is an atypical case (e.g. preparing .sql files
+      // before Civi has been installed), then we fallback to
+      // DB-less escaping helper (mysql_real_escape_string).
+      // Note: In typical usage, escapeString() will only
+      // check one conditional ("if !$_dao") rather than
+      // two conditionals ("if !defined(DSN)")
+      if (!defined('CIVICRM_DSN')) {
+        if (function_exists('mysql_real_escape_string')) {
+          return mysql_real_escape_string($string);
+        } else {
+          throw new CRM_Core_Exception("Cannot generate SQL. \"mysql_real_escape_string\" is missing. Have you installed PHP \"mysql\" extension?");
+        }
+      }
+
       $_dao = new CRM_Core_DAO();
     }
 
@@ -1454,11 +1533,13 @@ SELECT contact_id
   /**
    * Escape a list of strings for use with "WHERE X IN (...)" queries.
    *
-   * @param $strings array
-   * @param $default string the value to use if $strings has no elements
+   * @param $strings
+   *   Array.
+   * @param $default
+   *   String the value to use if $strings has no elements.
    * @return string eg "abc","def","ghi"
    */
-  static function escapeStrings($strings, $default = NULL) {
+  public static function escapeStrings($strings, $default = NULL) {
     static $_dao = NULL;
     if (!$_dao) {
       $_dao = new CRM_Core_DAO();
@@ -1477,7 +1558,7 @@ SELECT contact_id
    *
    * @return string
    */
-  static function escapeWildCardString($string) {
+  public static function escapeWildCardString($string) {
     // CRM-9155
     // ensure we escape the single characters % and _ which are mysql wild
     // card characters and could come in via sortByCharacter
@@ -1496,7 +1577,7 @@ SELECT contact_id
    * createOnly: only create in database, do not store or return the objects (useful for perf testing)
    * ONLY USE FOR TESTING
    *
-   * @param $daoName
+   * @param string $daoName
    * @param array $params
    * @param int $numObjects
    * @param bool $createOnly
@@ -1520,6 +1601,7 @@ SELECT contact_id
       'CRM_Core_DAO_StateProvince',
       'CRM_Core_DAO_Country',
       'CRM_Core_DAO_Domain',
+      'CRM_Financial_DAO_FinancialType'//because valid ones exist & we use pick them due to pseudoconstant can't reliably create & delete these
     );
 
     for ($i = 0; $i < $numObjects; ++$i) {
@@ -1570,14 +1652,13 @@ SELECT contact_id
   }
 
   /**
-   * deletes the this object plus any dependent objects that are associated with it
+   * Deletes the this object plus any dependent objects that are associated with it
    * ONLY USE FOR TESTING
    *
-   * @param $daoName
+   * @param string $daoName
    * @param array $params
    */
-  static function deleteTestObjects($daoName, $params = array(
-    )) {
+  public static function deleteTestObjects($daoName, $params = array()) {
     //this is a test function  also backtrace is set for the test suite it sometimes unsets itself
     // so we re-set here in case
     $config = CRM_Core_Config::singleton();
@@ -1599,7 +1680,10 @@ SELECT contact_id
         if ($FKClassName != NULL
           && $object->$dbName
           && !in_array($FKClassName, CRM_Core_DAO::$_testEntitiesToSkip)
-          && ($required || $dbName == 'contact_id')) {
+          && ($required || $dbName == 'contact_id')
+          //I'm a bit stuck on this one - we might need to change the singleValueAlter so that the entities don't share a contact
+          // to make this test process pass - line below makes pass for now
+          && $dbName != 'member_of_contact_id') {
           $deletions[] = array($FKClassName, array('id' => $object->$dbName)); // x
         }
       }
@@ -1612,6 +1696,24 @@ SELECT contact_id
   }
   }
 
+  /**
+   * Set defaults when creating new entity
+   * (don't call this set defaults as already in use with different signature in some places)
+   *
+   * @param array $params
+   * @param $defaults
+   */
+  public static function setCreateDefaults(&$params, $defaults) {
+    if (isset($params['id'])) {
+      return;
+    }
+    foreach ($defaults as $key => $value) {
+      if (!array_key_exists($key, $params) || $params[$key] === NULL) {
+        $params[$key] = $value;
+      }
+    }
+  }
+
   /**
    * @param string $prefix
    * @param bool $addRandomString
@@ -1619,7 +1721,7 @@ SELECT contact_id
    *
    * @return string
    */
-  static function createTempTableName($prefix = 'civicrm', $addRandomString = TRUE, $string = NULL) {
+  public static function createTempTableName($prefix = 'civicrm', $addRandomString = TRUE, $string = NULL) {
     $tableName = $prefix . "_temp";
 
     if ($addRandomString) {
@@ -1639,7 +1741,7 @@ SELECT contact_id
    *
    * @return bool
    */
-  static function checkTriggerViewPermission($view = TRUE, $trigger = TRUE) {
+  public static function checkTriggerViewPermission($view = TRUE, $trigger = TRUE) {
     // test for create view and trigger permissions and if allowed, add the option to go multilingual
     // and logging
     // I'm not sure why we use the getStaticProperty for an error, rather than checking for DB_Error
@@ -1684,7 +1786,7 @@ SELECT contact_id
    * @param null $message
    * @param bool $printDAO
    */
-  static function debugPrint($message = NULL, $printDAO = TRUE) {
+  public static function debugPrint($message = NULL, $printDAO = TRUE) {
     CRM_Utils_System::xMemory("{$message}: ");
 
     if ($printDAO) {
@@ -1701,12 +1803,13 @@ SELECT contact_id
    * Build a list of triggers via hook and add them to (err, reconcile them
    * with) the database.
    *
-   * @param $tableName string the specific table requiring a rebuild; or NULL to rebuild all tables
+   * @param $tableName
+   *   String the specific table requiring a rebuild; or NULL to rebuild all tables.
    * @param bool $force
    *
    * @see CRM-9716
    */
-  static function triggerRebuild($tableName = NULL, $force = FALSE) {
+  public static function triggerRebuild($tableName = NULL, $force = FALSE) {
     $info = array();
 
     $logging = new CRM_Logging_Schema;
@@ -1731,7 +1834,7 @@ SELECT contact_id
    *  * Stop using functions and find another way to strip numeric characters from phones
    *  * Give better error messages (currently a missing fn fatals with "unknown error")
    */
-  static function checkSqlFunctionsExist() {
+  public static function checkSqlFunctionsExist() {
     if (!self::$_checkedSqlFunctionsExist) {
       self::$_checkedSqlFunctionsExist = TRUE;
       $dao = CRM_Core_DAO::executeQuery("SHOW function status WHERE db = database() AND name = 'civicrm_strip_non_numeric'");
@@ -1744,9 +1847,10 @@ SELECT contact_id
   /**
    * Wrapper function to drop triggers
    *
-   * @param $tableName string the specific table requiring a rebuild; or NULL to rebuild all tables
+   * @param $tableName
+   *   String the specific table requiring a rebuild; or NULL to rebuild all tables.
    */
-  static function dropTriggers($tableName = NULL) {
+  public static function dropTriggers($tableName = NULL) {
     $info = array();
 
     $logging = new CRM_Logging_Schema;
@@ -1757,10 +1861,12 @@ SELECT contact_id
   }
 
   /**
-   * @param $info array per hook_civicrm_triggerInfo
-   * @param $onlyTableName string the specific table requiring a rebuild; or NULL to rebuild all tables
+   * @param $info
+   *   Array per hook_civicrm_triggerInfo.
+   * @param $onlyTableName
+   *   String the specific table requiring a rebuild; or NULL to rebuild all tables.
    */
-  static function createTriggers(&$info, $onlyTableName = NULL) {
+  public static function createTriggers(&$info, $onlyTableName = NULL) {
     // Validate info array, should probably raise errors?
     if (is_array($info) == FALSE) {
       return;
@@ -1868,10 +1974,11 @@ SELECT contact_id
   /**
    * Given a list of fields, create a list of references.
    *
-   * @param string $className BAO/DAO class name
+   * @param string $className
+   *   BAO/DAO class name.
    * @return array<CRM_Core_Reference_Interface>
    */
-  static function createReferenceColumns($className) {
+  public static function createReferenceColumns($className) {
     $result = array();
     $fields = $className::fields();
     foreach ($fields as $field) {
@@ -1893,7 +2000,7 @@ SELECT contact_id
    *
    * @return array of objects referencing this
    */
-  function findReferences() {
+  public function findReferences() {
     $links = self::getReferencesToTable(static::getTableName());
 
     $occurrences = array();
@@ -1921,7 +2028,7 @@ SELECT contact_id
    *  - table: string|null SQL table name
    *  - key: string|null SQL column name
    */
-  function getReferenceCounts() {
+  public function getReferenceCounts() {
     $links = self::getReferencesToTable(static::getTableName());
 
     $counts = array();
@@ -1951,12 +2058,13 @@ SELECT contact_id
    * schema metadata in dynamicForeignKey which enumerates a restricted
    * set of possible entity_table's.
    *
-   * @param string $tableName table referred to
+   * @param string $tableName
+   *   Table referred to.
    *
    * @return array structure of table and column, listing every table with a
    * foreign key reference to $tableName, and the column where the key appears.
    */
-  static function getReferencesToTable($tableName) {
+  public static function getReferencesToTable($tableName) {
     $refsFound = array();
     foreach (CRM_Core_DAO_AllCoreTables::getClasses() as $daoClassName) {
       $links = $daoClassName::getReferenceColumns();
@@ -1975,7 +2083,8 @@ SELECT contact_id
   /**
    * Lookup the value of a MySQL global configuration variable.
    *
-   * @param string $name e.g. "thread_stack"
+   * @param string $name
+   *   E.g. "thread_stack".
    * @param mixed $default
    * @return mixed
    */
@@ -1998,8 +2107,10 @@ SELECT contact_id
    * The overriding function will generally call the lower-level CRM_Core_PseudoConstant::get
    *
    * @param string $fieldName
-   * @param string $context : @see CRM_Core_DAO::buildOptionsContext
-   * @param array $props : whatever is known about this bao object
+   * @param string $context
+   *   : @see CRM_Core_DAO::buildOptionsContext.
+   * @param array $props
+   *   : whatever is known about this bao object.
    *
    * @return Array|bool
    */
@@ -2035,7 +2146,7 @@ SELECT contact_id
   /**
    * Provides documentation and validation for the buildOptions $context param
    *
-   * @param String $context
+   * @param string $context
    *
    * @throws Exception
    * @return array
@@ -2055,10 +2166,10 @@ SELECT contact_id
   }
 
   /**
-   * @param $fieldName
+   * @param string $fieldName
    * @return bool|array
    */
-  function getFieldSpec($fieldName) {
+  public function getFieldSpec($fieldName) {
     $fields = $this->fields();
     $fieldKeys = $this->fieldKeys();
 
@@ -2081,15 +2192,20 @@ SELECT contact_id
    * $field => array('LIKE' => array('%me%))
    * etc
    *
-   * @param $fieldName
-   * @param $filter array filter to be applied indexed by operator
-   * @param $type String type of field (not actually used - nor in api @todo )
-   * @param $alias String alternative field name ('as') @todo- not actually used
-   * @param bool $returnSanitisedArray return a sanitised array instead of a clause
+   * @param string $fieldName
+   *   Name of fields.
+   * @param $filter
+   *   Array filter to be applied indexed by operator.
+   * @param $type
+   *   String type of field (not actually used - nor in api @todo ).
+   * @param $alias
+   *   String alternative field name ('as') @todo- not actually used.
+   * @param bool $returnSanitisedArray
+   *   Return a sanitised array instead of a clause.
    *  this is primarily so we can add filters @ the api level to the Query object based fields
    *
    * @throws Exception
-   * @internal param string $fieldname name of fields
+   *
    * @todo a better solution would be for the query object to apply these filters based on the
    *  api supported format (but we don't want to risk breakage in alpha stage & query class is scary
    * @todo @time of writing only IN & NOT IN are supported for the array style syntax (as test is
@@ -2109,10 +2225,10 @@ SELECT contact_id
           // unary operators
           case 'IS NULL':
           case 'IS NOT NULL':
-            if(!$returnSanitisedArray) {
+            if (!$returnSanitisedArray) {
               return (sprintf('%s %s', $fieldName, $operator));
             }
-            else{
+            else {
               return (sprintf('%s %s ', $fieldName, $operator));
             }
             break;
@@ -2123,10 +2239,10 @@ SELECT contact_id
             if (empty($criteria[0]) || empty($criteria[1])) {
               throw new Exception("invalid criteria for $operator");
             }
-            if(!$returnSanitisedArray) {
+            if (!$returnSanitisedArray) {
               return (sprintf('%s ' . $operator . ' "%s" AND "%s"', $fieldName, CRM_Core_DAO::escapeString($criteria[0]), CRM_Core_DAO::escapeString($criteria[1])));
             }
-            else{
+            else {
               return NULL;  // not yet implemented (tests required to implement)
             }
             break;
@@ -2141,7 +2257,7 @@ SELECT contact_id
               'CRM_Core_DAO',
               'escapeString'
             ), $criteria);
-            if(!$returnSanitisedArray) {
+            if (!$returnSanitisedArray) {
               return (sprintf('%s %s ("%s")', $fieldName, $operator, implode('", "', $escapedCriteria)));
             }
             return $escapedCriteria;
@@ -2150,10 +2266,10 @@ SELECT contact_id
           // binary operators
 
           default:
-            if(!$returnSanitisedArray) {
+            if (!$returnSanitisedArray) {
               return(sprintf('%s %s "%s"', $fieldName, $operator, CRM_Core_DAO::escapeString($criteria)));
             }
-            else{
+            else {
               return NULL; // not yet implemented (tests required to implement)
             }
         }
@@ -2178,8 +2294,10 @@ SELECT contact_id
    * which can be longer than this length, this function helps with creating
    * strings that meet various criteria.
    *
-   * @param string $string - the string to be shortened
-   * @param int $length - the max length of the string
+   * @param string $string
+   *   The string to be shortened.
+   * @param int $length
+   *   The max length of the string.
    *
    * @param bool $makeRandom
    *
@@ -2192,7 +2310,7 @@ SELECT contact_id
     }
 
     // easy return for calls that dont need a randomized uniq string
-    if (! $makeRandom) {
+    if (!$makeRandom) {
       return substr($string, 0, $length);
     }
 
@@ -2205,8 +2323,8 @@ SELECT contact_id
   }
 
   /**
-   * @param $params
+   * @param array $params
    */
-  function setApiFilter(&$params) {}
+  public function setApiFilter(&$params) {}
 
 }