| 1 |
<?php
|
| 2 |
/*
|
| 3 |
* Some radioactivity functions that may be called from other modules, even when the main radioactivity
|
| 4 |
* is not loaded. For instance, radioactivity_node utilizes this in radioactivity_node_exit.
|
| 5 |
*/
|
| 6 |
|
| 7 |
/**
|
| 8 |
* Returns target object classes. Objects of target classes may receive energy.
|
| 9 |
*/
|
| 10 |
function radioactivity_get_radioactivity_info($reset_cache=FALSE) {
|
| 11 |
static $info;
|
| 12 |
|
| 13 |
if ($reset_cache || !isset($info)) {
|
| 14 |
$info = array('targets' => array(), 'sources' => array());
|
| 15 |
foreach (module_implements('radioactivity_info') as $name) {
|
| 16 |
$function = $name .'_radioactivity_info';
|
| 17 |
$result = $function();
|
| 18 |
if (isset($result) && is_array($result)) {
|
| 19 |
$info = array_merge_recursive($info, $result);
|
| 20 |
}
|
| 21 |
}
|
| 22 |
}
|
| 23 |
|
| 24 |
return $info;
|
| 25 |
}
|
| 26 |
|
| 27 |
/**
|
| 28 |
* Retrieves decay profiles in array. The array key is decay profile id (positive int) and the value is the decay
|
| 29 |
* profile. The profile is array as follows:
|
| 30 |
* "label" -> The profile label
|
| 31 |
* "description -> The profile description
|
| 32 |
* "half_life" -> The radioactivity half-life (in seconds)
|
| 33 |
*/
|
| 34 |
function _radioactivity_get_decay_profiles() {
|
| 35 |
$decay_profiles=variable_get("radioactivity_profiles", array());
|
| 36 |
|
| 37 |
return $decay_profiles;
|
| 38 |
}
|
| 39 |
|
| 40 |
function _radioactivity_possibly_remap_id($oid, $oclass) {
|
| 41 |
static $map=array();
|
| 42 |
if (!isset($map[$oclass][$oid])) {
|
| 43 |
$info=radioactivity_get_radioactivity_info();
|
| 44 |
$function=$info['targets'][$oclass]['id_mapper'];
|
| 45 |
if ($function) {
|
| 46 |
$new_oid=$function($oid, $oclass);
|
| 47 |
} else {
|
| 48 |
$new_oid=$oid;
|
| 49 |
}
|
| 50 |
$map[$oclass][$oid]=$new_oid;
|
| 51 |
}
|
| 52 |
return $map[$oclass][$oid];
|
| 53 |
}
|
| 54 |
|
| 55 |
/**
|
| 56 |
* Resolve full class name for a specific object. This utilizes subclass resolver if defined.
|
| 57 |
*/
|
| 58 |
function _radioactivity_resolve_classname($oid, $oclass) {
|
| 59 |
static $map=array();
|
| 60 |
|
| 61 |
if (!isset($map[$oclass][$oid])) {
|
| 62 |
$info=radioactivity_get_radioactivity_info();
|
| 63 |
$function=$info['targets'][$oclass]['subclass_resolver'];
|
| 64 |
if ($function) {
|
| 65 |
$subclass=$function($oid, $oclass);
|
| 66 |
if ($subclass) {
|
| 67 |
$classname=$oclass.':'.$subclass;
|
| 68 |
} else {
|
| 69 |
$classname=$oclass;
|
| 70 |
}
|
| 71 |
} else {
|
| 72 |
$classname=$oclass;
|
| 73 |
}
|
| 74 |
$map[$oclass][$oid]=$classname;
|
| 75 |
}
|
| 76 |
return $map[$oclass][$oid];
|
| 77 |
}
|
| 78 |
|
| 79 |
/**
|
| 80 |
* Return energies for source action.
|
| 81 |
* @param $oid
|
| 82 |
* @param $oclass Base class, e.g. 'node'. Subclass will be resolved by subclass_resolver hook if necessary
|
| 83 |
* @param $source Energy source, e.g. 'view'
|
| 84 |
* @return array of dpid to energy, e.g, array(1 => 3.4, 2 => 5.6);
|
| 85 |
*/
|
| 86 |
function radioactivity_get_energies_for_source($oid, $oclass, $source) {
|
| 87 |
$ret=array();
|
| 88 |
foreach (_radioactivity_get_decay_profiles() as $dpid => $decay_profile) {
|
| 89 |
$classname=$oclass; // the default class name
|
| 90 |
|
| 91 |
// check if we need to resolve full classname
|
| 92 |
if (is_array($decay_profile['energy'][$oclass]['subclasses'])) {
|
| 93 |
foreach ($decay_profile['energy'][$oclass]['subclasses'] as $subsources) {
|
| 94 |
if (isset($subsources[$source])) {
|
| 95 |
// there is subclass specific energy value for the source, so
|
| 96 |
// resolve subclass
|
| 97 |
$classname=_radioactivity_resolve_classname($oid, $oclass);
|
| 98 |
break;
|
| 99 |
}
|
| 100 |
}
|
| 101 |
}
|
| 102 |
|
| 103 |
// resolve energy amount
|
| 104 |
$energy=$decay_profile['energy'];
|
| 105 |
$value=0;
|
| 106 |
$classparts=explode(':', $classname);
|
| 107 |
|
| 108 |
foreach ($classparts as $part) {
|
| 109 |
if (!is_array($energy[$part])) break;
|
| 110 |
$energy=$energy[$part];
|
| 111 |
$value_cand=$energy[$source];
|
| 112 |
if (strlen($value_cand)>0) $value=(double)$value_cand;
|
| 113 |
$energy=$energy['subclasses'];
|
| 114 |
}
|
| 115 |
|
| 116 |
$ret[$dpid]=$value;
|
| 117 |
}
|
| 118 |
return $ret;
|
| 119 |
}
|
| 120 |
|
| 121 |
// this is the MySQL optimized version
|
| 122 |
function _radioactivity_add_energy_mysql($oid, $oclass, $dpid, $amount, $timestamp) {
|
| 123 |
db_query("INSERT INTO {radioactivity} (id, class, decay_profile, energy, last_emission_timestamp) ".
|
| 124 |
"VALUES (%d, '%s', %d, %f, %d) ON DUPLICATE KEY UPDATE energy=energy+%f",
|
| 125 |
$oid, $oclass, $dpid, $amount, $timestamp, $amount);
|
| 126 |
}
|
| 127 |
|
| 128 |
// standards compliant version
|
| 129 |
function _radioactivity_add_energy_std($oid, $oclass, $dpid, $amount, $timestamp) {
|
| 130 |
db_query("UPDATE {radioactivity} SET energy=energy+%f ".
|
| 131 |
"WHERE id=%d AND class='%s' AND decay_profile=%d", $amount, $oid, $oclass, $dpid);
|
| 132 |
|
| 133 |
if (db_affected_rows()==0) {
|
| 134 |
// No new rows, try update again and insert one if necessary.
|
| 135 |
// Note that we do the second update inside lock table to be certain that there wasn't insert
|
| 136 |
// after the last update.
|
| 137 |
|
| 138 |
db_lock_table("radioactivity");
|
| 139 |
$result=db_query("UPDATE {radioactivity} SET energy=energy+%f ".
|
| 140 |
"WHERE id=%d AND class='%s' AND decay_profile=%d", $amount, $oid, $oclass, $dpid);
|
| 141 |
|
| 142 |
if (db_affected_rows()==0) {
|
| 143 |
db_query("INSERT INTO {radioactivity} (id, class, decay_profile, energy, last_emission_timestamp) ".
|
| 144 |
"VALUES (%d, '%s', %d, %f, %d)",
|
| 145 |
$oid, $oclass, $dpid, $amount, $timestamp);
|
| 146 |
}
|
| 147 |
db_unlock_tables();
|
| 148 |
}
|
| 149 |
}
|
| 150 |
|
| 151 |
/**
|
| 152 |
* Add energy to nodes.
|
| 153 |
* @param $oid Object id
|
| 154 |
* @param $oclass Object base class, e.g. 'node'. Subclass will be resolved if necessary
|
| 155 |
* @param $source Energy source, e.g. 'view'
|
| 156 |
* @return TRUE if successful
|
| 157 |
*/
|
| 158 |
function radioactivity_add_energy($oid, $oclass, $source) {
|
| 159 |
$db_type=$GLOBALS['db_type'];
|
| 160 |
$timestamp=time();
|
| 161 |
|
| 162 |
$energies=radioactivity_get_energies_for_source($oid, $oclass, $source);
|
| 163 |
|
| 164 |
foreach ($energies as $dpid => $amount) {
|
| 165 |
|
| 166 |
if ($amount==0) continue;
|
| 167 |
|
| 168 |
// remap id if necessary
|
| 169 |
$oid=_radioactivity_possibly_remap_id($oid, $oclass);
|
| 170 |
|
| 171 |
switch ($db_type) {
|
| 172 |
case 'mysql':
|
| 173 |
case 'mysqli':
|
| 174 |
_radioactivity_add_energy_mysql($oid, $oclass, $dpid, $amount, $timestamp);
|
| 175 |
break;
|
| 176 |
|
| 177 |
case 'pgsql':
|
| 178 |
_radioactivity_add_energy_std($oid, $oclass, $dpid, $amount, $timestamp);
|
| 179 |
break;
|
| 180 |
|
| 181 |
default:
|
| 182 |
watchdog('radioactivity', t('Unsupported database: @db_type', array('@db_type' => $db_type)), WATCHDOG_ERROR);
|
| 183 |
break;
|
| 184 |
}
|
| 185 |
}
|
| 186 |
|
| 187 |
return TRUE;
|
| 188 |
}
|