| 1 |
<?php
|
| 2 |
/**
|
| 3 |
* $Id: carbon_stamp.inc,v 1.33 2009/06/01 17:05:18 johnackers Exp $
|
| 4 |
*
|
| 5 |
* Drupal carbon stamp module.
|
| 6 |
*
|
| 7 |
* A carbon stamp is a record of an activity that resulted in CO2 emission.
|
| 8 |
*
|
| 9 |
* Created on 18-Oct-2006
|
| 10 |
*
|
| 11 |
*/
|
| 12 |
|
| 13 |
|
| 14 |
/**
|
| 15 |
* Implementation of hook_access().
|
| 16 |
*
|
| 17 |
* Delegate carbon_access to the carbon module because it
|
| 18 |
* is easier to check access for all carbon types in one place.
|
| 19 |
*/
|
| 20 |
|
| 21 |
function carbon_stamp_access($op, $node)
|
| 22 |
{
|
| 23 |
return carbon_access($op, $node);
|
| 24 |
}
|
| 25 |
|
| 26 |
|
| 27 |
/**
|
| 28 |
* Render a page listing a one line summary of all carbon footprints
|
| 29 |
*/
|
| 30 |
|
| 31 |
|
| 32 |
function carbon_stamp_page($aid, $target_user, $meterPage) {
|
| 33 |
global $user;
|
| 34 |
|
| 35 |
$header = array(
|
| 36 |
array("data" => t("title"), "field" => "title"),
|
| 37 |
array("data" => t("start"), "field" => "startdate"),
|
| 38 |
array("data" => t("end"), "field" => "enddate"),
|
| 39 |
array("data" => t("code"), "field" => "code"),
|
| 40 |
array("data" => t("amount"), "field" => "reading"),
|
| 41 |
array("data" => t("fp's"), "field" => "numfoot"),
|
| 42 |
array("data" => t("status"), "field" => "status"),
|
| 43 |
array("data" => t("operations"))
|
| 44 |
);
|
| 45 |
|
| 46 |
if (empty($uid))
|
| 47 |
$header[] = array("data" => t("author"),"field" => "name");
|
| 48 |
|
| 49 |
$sql = carbon_stamp_query($aid, $target_user->uid, null, $meterPage);
|
| 50 |
|
| 51 |
$sql .= tablesort_sql($header);
|
| 52 |
|
| 53 |
// get the links (no range limit here)
|
| 54 |
$queryResult = db_query($sql);
|
| 55 |
|
| 56 |
while ($node = db_fetch_object($queryResult))
|
| 57 |
{
|
| 58 |
$node->protection = _log2($node->protect2);
|
| 59 |
$ro_access = carbon_access("view", $node);
|
| 60 |
if ($ro_access)
|
| 61 |
{
|
| 62 |
$row = array(carbon_link_from_title($node, $node, ""),
|
| 63 |
$node->startdate == 0 ? '' : _format_date_time($node->startdate),
|
| 64 |
_format_date_time($node->enddate),
|
| 65 |
$node->code,
|
| 66 |
$node->reading.' '._get_scope_key($node->scope),
|
| 67 |
$node->numfoot <= 1 ? (isset($node->sid) ? 1 : 0) : $node->numfoot,
|
| 68 |
$node->status >= 1 ? 'pub' : '',
|
| 69 |
$node->protection . " " . carbon_format_edit_ops($node, null));
|
| 70 |
|
| 71 |
if (empty($uid))
|
| 72 |
$row[] = $node->name ;
|
| 73 |
$rows[] = $row ;
|
| 74 |
}
|
| 75 |
}
|
| 76 |
|
| 77 |
$output = theme("table", $header, $rows);
|
| 78 |
$output .= theme("pager", NULL, 10, 0);
|
| 79 |
|
| 80 |
if ($params["datatype"] == "json")
|
| 81 |
{
|
| 82 |
$output = drupal_json($output);
|
| 83 |
print($output);
|
| 84 |
exit(0);
|
| 85 |
}
|
| 86 |
|
| 87 |
$title = t("Carbon Stamps");
|
| 88 |
|
| 89 |
if (!empty($target_user))
|
| 90 |
$title .= t(" owned by !name", array("!name" => $target_user->name));
|
| 91 |
|
| 92 |
drupal_set_title(check_plain($title));
|
| 93 |
|
| 94 |
return $output;
|
| 95 |
}
|
| 96 |
|
| 97 |
|
| 98 |
function carbon_stamp_query($aid, $uid, $nid, $meterPage)
|
| 99 |
{
|
| 100 |
$sql = "SELECT t.*, n.title, n.nid, n.status, n.uid, n.type, name, count(*) as numfoot, " .
|
| 101 |
"BIT_OR(POWER(2,a.protection)) as protect2, j.sid " .
|
| 102 |
"FROM {carbon_stamp} t " .
|
| 103 |
"INNER JOIN {node} n ON t.nid = n.nid " .
|
| 104 |
"INNER JOIN {users} u ON n.uid = u.uid " .
|
| 105 |
"LEFT JOIN {carbon_stamp_account} j ON t.nid = j.sid " .
|
| 106 |
"LEFT JOIN {carbon_account} a ON j.fid = a.nid " .
|
| 107 |
"WHERE TRUE " .
|
| 108 |
(empty($aid) ? '' : " AND a.nid = ".$aid. " ") .
|
| 109 |
(empty($uid) ? '' : " AND n.uid = ".$uid. " ") .
|
| 110 |
(empty($nid) ? '' : " AND n.nid = ".$nid. " ") .
|
| 111 |
(!isset($meterPage) ? '' : " AND t.scope". ($meterPage ? "=1 " : "!=1 ")) .
|
| 112 |
"GROUP BY t.nid ";
|
| 113 |
|
| 114 |
return $sql ;
|
| 115 |
}
|
| 116 |
|
| 117 |
|
| 118 |
/**
|
| 119 |
* convert
|
| 120 |
*
|
| 121 |
* @param $protect
|
| 122 |
* @return converted number
|
| 123 |
*
|
| 124 |
*/
|
| 125 |
|
| 126 |
function _log2($protect2)
|
| 127 |
{
|
| 128 |
$k = 0 ;
|
| 129 |
for ($i = 1 ; $i < $protect2 ; $i *= 2)
|
| 130 |
$k++ ;
|
| 131 |
return $k ;
|
| 132 |
}
|
| 133 |
|
| 134 |
|
| 135 |
|
| 136 |
function carbon_stamp_header()
|
| 137 |
{
|
| 138 |
global $carbon_stamp_header ;
|
| 139 |
if (!isset($carbon_stamp_header))
|
| 140 |
{
|
| 141 |
$carbon_stamp_header = array(
|
| 142 |
array("data" => t("date"), "field" => "enddate", "sort" => "asc"),
|
| 143 |
array("data" => t("title"), "field" => "sourcetitle"),
|
| 144 |
array("data" => t("model"), "field" => "sourcemodel"),
|
| 145 |
array("data" => t("emission"),"field" => "title"),
|
| 146 |
array("data" => t("amount"), "field" => "reading"),
|
| 147 |
array("data" => t("units"), "field" => "units"),
|
| 148 |
array("data" => t("adjust"), "field" => "adjustment"));
|
| 149 |
}
|
| 150 |
// array("data" => t("type or size")),
|
| 151 |
return $carbon_stamp_header ;
|
| 152 |
}
|
| 153 |
|
| 154 |
/**
|
| 155 |
*
|
| 156 |
* Joins the recorded stamps in a carbon account with all the available carbon
|
| 157 |
* sources.
|
| 158 |
*
|
| 159 |
* Note that some source fields have been renamed e.g. sourceid, sourceclass, sourcetitle
|
| 160 |
*
|
| 161 |
*@param $nid select stamps attached to this footprint id, can be null
|
| 162 |
*@param $uid select stamps with this uid, can be null
|
| 163 |
*@param $org select stamps with this org, can be null
|
| 164 |
*@return an array of carbon stamps
|
| 165 |
*/
|
| 166 |
|
| 167 |
|
| 168 |
function carbon_stamp_array_load($nid, $uid, $org)
|
| 169 |
{
|
| 170 |
/**
|
| 171 |
* this is a very tricky SQL statment. It is currently arranged to
|
| 172 |
* show all carbon stamps that do not have a matching carbon source
|
| 173 |
* so that user can be warned.
|
| 174 |
*/
|
| 175 |
|
| 176 |
$query ="SELECT nstamp.title, nstamp.status, nstamp.uid, nstamp.type, stamp.*, s.uid AS shared_uid, " .
|
| 177 |
"nsource.title as sourcetitle, source.nid as sourceid, source.code as sourcecode, ".
|
| 178 |
"source.classname as sourceclass, nsource.status as sourcestatus, ".
|
| 179 |
"source.sector, source.model as sourcemodel, units, tokwh0, tokwh1, toco2, params, " .
|
| 180 |
"f.model as preferred_model, f.organization, f.enablekwh0, f.enablekwh1, f.enableco2 " .
|
| 181 |
"FROM {carbon_stamp} stamp " .
|
| 182 |
"LEFT JOIN {carbon_source} source ON stamp.code=source.code " .
|
| 183 |
"LEFT JOIN {carbon_stamp_account} j ON stamp.nid = j.sid " .
|
| 184 |
"INNER JOIN {carbon_account} f ON f.nid = j.fid " .
|
| 185 |
"LEFT JOIN {carbon_account_share} s ON f.nid = s.nid " .
|
| 186 |
"INNER JOIN {node} nstamp ON stamp.nid = nstamp.nid ".
|
| 187 |
"LEFT JOIN {node} nsource ON source.nid = nsource.nid ".
|
| 188 |
"WHERE nstamp.status ". // stamp must be published
|
| 189 |
// "AND nsource.status ". // source must be published
|
| 190 |
"AND (j.fid = %d " . (empty($nid) ? " OR 1) " : ") ").
|
| 191 |
"AND (nstamp.uid = %d " . (empty($uid) ? " OR 1) " : ") ").
|
| 192 |
"AND (f.organization = '%s' " . (empty($org) ? " OR 1) " : ") ").
|
| 193 |
"" ;
|
| 194 |
|
| 195 |
// $query = db_rewrite_sql($query);
|
| 196 |
// drupal_set_message(" my sql ". $query, "info");
|
| 197 |
|
| 198 |
$query .= tablesort_sql(carbon_stamp_header());
|
| 199 |
$queryResult = db_query($query, $nid, $uid, $org);
|
| 200 |
|
| 201 |
$stamps = array();
|
| 202 |
$sources = array();
|
| 203 |
$num = 0 ;
|
| 204 |
while ($record = db_fetch_object($queryResult))
|
| 205 |
{
|
| 206 |
$stamps[] = $record ;
|
| 207 |
}
|
| 208 |
$filtered_stamps = _select_stamps_from_preferred_sources($stamps);
|
| 209 |
|
| 210 |
return $filtered_stamps;
|
| 211 |
}
|
| 212 |
|
| 213 |
|
| 214 |
function _stamp_form(&$form, $stamp, $carbonSources)
|
| 215 |
{
|
| 216 |
$form["stamp"] = array(
|
| 217 |
"#type" => "fieldset",
|
| 218 |
"#title" => "Carbon stamp",
|
| 219 |
"#weight" => -3,
|
| 220 |
"#collapsible" => TRUE,
|
| 221 |
"#collapsed" => FALSE);
|
| 222 |
|
| 223 |
$form["stamp"]["title"] = array(
|
| 224 |
"#type" => "textfield",
|
| 225 |
"#title" => t("description"),
|
| 226 |
"#required" => true,
|
| 227 |
"#default_value" => empty($stamp->title) ? "" : $stamp->title ,
|
| 228 |
"#size" => 20,
|
| 229 |
"#maxlength" => 255,
|
| 230 |
"#weight" => -2,
|
| 231 |
"#description" =>
|
| 232 |
_div_wrap("scope-0",t("Name of activity e.g. train to Leeds")).
|
| 233 |
_div_wrap("scope-1",t("Meter name e.g. gas. " .
|
| 234 |
"This must be the same for all readings from the same meter.")).
|
| 235 |
_div_wrap("scope-2",t("Name of repeating activity e.g. annual gas bill"))
|
| 236 |
);
|
| 237 |
|
| 238 |
$form["stamp"]["scope_index"] = array(
|
| 239 |
"#attributes" => array("class"=>"scope"),
|
| 240 |
"#type" => "radios",
|
| 241 |
"#title" => t("type of carbon stamp"),
|
| 242 |
"#required" => FALSE,
|
| 243 |
"#options" => _get_scope_description(),
|
| 244 |
"#size" => 14,
|
| 245 |
"#maxlength" => 20,
|
| 246 |
"#weight" => -1, // $stamp->scope can be 0 !
|
| 247 |
"#default_value" => isset($stamp->scope) ? $stamp->scope : 1,
|
| 248 |
"#description" =>
|
| 249 |
_div_wrap("scope-0",t("A one off emission can be used for single journeys ")).
|
| 250 |
_div_wrap("scope-1",t("Note that meter readings are subtracted from one another " .
|
| 251 |
"to calculate consumption. You need to have at least two meter readings before this " .
|
| 252 |
"source of emissions will be included in your carbon footprint. You need not specify " .
|
| 253 |
"start or end dates, just the date the meter was read.")).
|
| 254 |
_div_wrap("scope-2",t("A source of emissions that regularly repeats. Enter the the number ".
|
| 255 |
"of days per year in the adjustment field below. ".
|
| 256 |
"Use the start and stop dates as needed."))
|
| 257 |
);
|
| 258 |
|
| 259 |
$form["stamp"]["code_index"] = array(
|
| 260 |
"#type" => "select",
|
| 261 |
"#title" => t("select source of emissions"),
|
| 262 |
"#required" => FALSE,
|
| 263 |
"#options" => $carbonSources->values(),
|
| 264 |
"#default_value" => empty($stamp->code) ? 0 : array_search($stamp->code, $carbonSources->keys()),
|
| 265 |
"#size" => 1,
|
| 266 |
"#maxlength" => 20,
|
| 267 |
"#weight" => 0,
|
| 268 |
"#description" => t("Select from pull down list of emissions configured for this site."));
|
| 269 |
|
| 270 |
$form["stamp"]["reading"] = array(
|
| 271 |
"#type" => "textfield",
|
| 272 |
"#title" => t("amount"),
|
| 273 |
"#required" => true,
|
| 274 |
"#default_value" => empty($stamp->reading) ? "" : $stamp->reading,
|
| 275 |
"#size" => 8,
|
| 276 |
"#maxlength" => 20,
|
| 277 |
"#weight" => 0,
|
| 278 |
"#description" =>
|
| 279 |
"<div class='scope-0'>"._help_on_distance()."</div>".
|
| 280 |
"<div class='scope-1'>".t("Enter meter reading")."</div>".
|
| 281 |
"<div class='scope-2'>"._help_on_distance()."</div>"
|
| 282 |
);
|
| 283 |
|
| 284 |
$form["stamp"]["startdate_s"] = array(
|
| 285 |
"#type" => "textfield",
|
| 286 |
"#title" => t("starting date"),
|
| 287 |
"#required" => FALSE,
|
| 288 |
"#default_value" => empty($stamp->startdate) ? "" : _format_date_time($stamp->startdate),
|
| 289 |
"#size" => 10,
|
| 290 |
"#maxlength" => 20,
|
| 291 |
"#weight" => 1,
|
| 292 |
"#prefix" => "<div class='startdate'>",
|
| 293 |
"#suffix" => "</div>",
|
| 294 |
"#description" =>
|
| 295 |
t("Format: %time.",
|
| 296 |
array("%time" => _format_date_only(time()))).
|
| 297 |
_div_wrap("scope-0",t("The first date of the activity. Leave blank".
|
| 298 |
" except when you are specifying an activity that spreads over days or weeks".
|
| 299 |
" such as the total distance travelled by bus over the last month or two.")).
|
| 300 |
_div_wrap("scope-1",t("Not used")).
|
| 301 |
_div_wrap("scope-2",t("The first date that this repeating event started.")));
|
| 302 |
|
| 303 |
$form["stamp"]["enddate_s"] = array(
|
| 304 |
"#type" => "textfield",
|
| 305 |
"#title" => t("date"),
|
| 306 |
"#required" => FALSE,
|
| 307 |
"#default_value" => $stamp->enddate == 0 ? "" : _format_date_time($stamp->enddate),
|
| 308 |
"#size" => 10,
|
| 309 |
"#maxlength" => 20,
|
| 310 |
"#weight" => 2,
|
| 311 |
"#description" =>
|
| 312 |
t("Format: %time. Leave blank to use today's date. ",
|
| 313 |
array("%time" => _format_date_time(time()))).
|
| 314 |
_div_wrap("scope-0",t("The last date of the activity")).
|
| 315 |
_div_wrap("scope-1",t("The date that the meter was read")).
|
| 316 |
_div_wrap("scope-2",t("The day after the last date on which this repeating event stopped.")));
|
| 317 |
|
| 318 |
|
| 319 |
$help_shared_heating = t("<h4>Sharing heating, electricity or a car trip</h4>" .
|
| 320 |
"For example if you are sharing with 4 people you might enter <b>1/4</b>.");
|
| 321 |
|
| 322 |
$help_repeating_trips = t(
|
| 323 |
"<h4>For an Annual Return Trip</h4>Enter <b>2</b> ".
|
| 324 |
"<h4>For a Frequent Trip</h4>Enter the number of days each year that you make this trip. ".
|
| 325 |
"For a monthly return trip, enter <b>2*12</b>. ".
|
| 326 |
"<h4>For a daily commute to work</h4> Assuming you take 5 weeks holiday, you " .
|
| 327 |
"might want to enter <b>2*220</b>. ");
|
| 328 |
|
| 329 |
$form["stamp"]["adjustment"] = array(
|
| 330 |
"#type" => "textfield",
|
| 331 |
"#title" => t("adjustment"),
|
| 332 |
"#required" => FALSE,
|
| 333 |
"#default_value" => $stamp != null && $stamp->adjustment != 0 ? $stamp->adjustment : 1,
|
| 334 |
"#weight" => 3,
|
| 335 |
"#size" => 6,
|
| 336 |
"#maxlength" => 20,
|
| 337 |
"#description" => t("Multiply emissions or energy up to the date of this reading by this number. Normally left blank but:").
|
| 338 |
_div_wrap("scope-0",t($help_shared_heating)).
|
| 339 |
_div_wrap("scope-1",t($help_shared_heating)).
|
| 340 |
_div_wrap("scope-2",t($help_repeating_trips)));
|
| 341 |
|
| 342 |
$form["stamp"]["code"] = array(
|
| 343 |
"#type" => "hidden",
|
| 344 |
"#value" => null);
|
| 345 |
}
|
| 346 |
|
| 347 |
function _help_on_distance()
|
| 348 |
{
|
| 349 |
return (
|
| 350 |
t("Number of units, miles, gallons, litres, KwH etc. "). t("Calculate distance between ").
|
| 351 |
l(t("airports around the world"), "http://www.timeanddate.com/worldclock/distance.html",
|
| 352 |
array("TARGET" => "distance_calculation_global"))." or between ".
|
| 353 |
l(t("local towns"), "http://co2balance.uk.com/co2calculators/rail-travel/",
|
| 354 |
array("TARGET" => "distance_calculation_local")))." ".
|
| 355 |
t("Enter one way distances and set adjust to 2 for return trips");
|
| 356 |
}
|
| 357 |
|
| 358 |
|
| 359 |
|
| 360 |
/**
|
| 361 |
* When a user creates or edits a carbon_stamp, s/he may want to
|
| 362 |
* add or remove it from a particular carbon footprint. This
|
| 363 |
* form is only attached when individual carbon stamps are
|
| 364 |
* edited.
|
| 365 |
*/
|
| 366 |
|
| 367 |
function _add_footprint_select(&$form, $node)
|
| 368 |
{
|
| 369 |
global $user ;
|
| 370 |
|
| 371 |
// find all the carbon footprints owned by the same user as this stamp
|
| 372 |
// or , if this is a new stamp, the logged in user. This is really to
|
| 373 |
// make testing easier.
|
| 374 |
|
| 375 |
$uid = isset($node->uid) ? $node->uid : $user->uid ;
|
| 376 |
$queryResult = db_query("SELECT n.nid,n.title from {node} n ".
|
| 377 |
" INNER JOIN {carbon_account} f ON n.nid=f.nid ".
|
| 378 |
" WHERE type='carbon_account' and uid = ".$uid);
|
| 379 |
|
| 380 |
|
| 381 |
// get all the normal attachments
|
| 382 |
while ($record = db_fetch_object($queryResult))
|
| 383 |
{
|
| 384 |
$options[$record->nid] = $record->title ;
|
| 385 |
}
|
| 386 |
|
| 387 |
$ticked_boxes = is_array($node->aid_map) ? $node->aid_map : array();
|
| 388 |
|
| 389 |
// add all the existing attachments which include footprints
|
| 390 |
// belonging to other UIDs.
|
| 391 |
|
| 392 |
foreach($ticked_boxes as $nid => $title)
|
| 393 |
$options[$nid] = $title ;
|
| 394 |
|
| 395 |
|
| 396 |
$form['attach'] = array(
|
| 397 |
"#type" => "fieldset",
|
| 398 |
"#weight" => -2,
|
| 399 |
"#title" => t("Select carbon account(s)"),
|
| 400 |
"#collapsible" => TRUE,
|
| 401 |
"#collapsed" => FALSE);
|
| 402 |
|
| 403 |
$f = &$form['attach'];
|
| 404 |
|
| 405 |
// this clumsy code sets the only check box if this is a new
|
| 406 |
// carbon stamp and there is only one footprint to attach to
|
| 407 |
|
| 408 |
if (empty($node->nid) && empty($exist) && count($options) == 1)
|
| 409 |
{
|
| 410 |
$ticked_boxes = $options;
|
| 411 |
}
|
| 412 |
|
| 413 |
// if there is only one option and it is ticked, collapse the frame
|
| 414 |
|
| 415 |
if (count($options) == 1 && count($ticked_boxes) == 1)
|
| 416 |
{
|
| 417 |
$f["#collapsed"] = true;
|
| 418 |
}
|
| 419 |
|
| 420 |
$f["aid_map_updated"] = array(
|
| 421 |
"#type" => "checkboxes",
|
| 422 |
"#default_value" => array_keys($ticked_boxes),
|
| 423 |
"#options" => $options,
|
| 424 |
"#description" => t("Select the the carbon accounts to which you would like to attach this carbon stamp.")
|
| 425 |
);
|
| 426 |
}
|
| 427 |
|
| 428 |
/**
|
| 429 |
*
|
| 430 |
*
|
| 431 |
* @param $node
|
| 432 |
* @param $form_state
|
| 433 |
* @return the constructed form
|
| 434 |
*/
|
| 435 |
|
| 436 |
|
| 437 |
function carbon_stamp_form(&$node, $form_state) {
|
| 438 |
global $user, $aid_map;
|
| 439 |
|
| 440 |
$form = array();
|
| 441 |
/*
|
| 442 |
if (count($source_descriptions) == 0)
|
| 443 |
{
|
| 444 |
$form["no-sources"] = array(
|
| 445 |
"#type" => "item",
|
| 446 |
"#value" => carbon_source_missing());
|
| 447 |
return $form ;
|
| 448 |
}
|
| 449 |
*/
|
| 450 |
_stamp_form($form, $node, CarbonSources::getDefault());
|
| 451 |
_add_footprint_select($form , $node, 0 , 0 );
|
| 452 |
$form['#submit'] = array('carbon_stamp_submit');
|
| 453 |
|
| 454 |
$path = carbon_include_core_js();
|
| 455 |
drupal_add_js($path . "/carbon_debug.js", "module");
|
| 456 |
|
| 457 |
return $form ;
|
| 458 |
}
|
| 459 |
|
| 460 |
/**
|
| 461 |
* scope is held as a integer in the database which
|
| 462 |
* indexes this map directly, so take care about changing the
|
| 463 |
* order of the entries in the table.
|
| 464 |
*/
|
| 465 |
|
| 466 |
function _scope_map()
|
| 467 |
{
|
| 468 |
return array(
|
| 469 |
"" => t("a single event"),
|
| 470 |
"m" => t("a meter or mileometer reading"),
|
| 471 |
"r" => t("an annually repeating event")
|
| 472 |
);
|
| 473 |
}
|
| 474 |
|
| 475 |
|
| 476 |
/**
|
| 477 |
* @return a short code/description of this numeric scope value
|
| 478 |
*/
|
| 479 |
|
| 480 |
function _get_scope_key($i)
|
| 481 |
{
|
| 482 |
global $scope_keys ;
|
| 483 |
if (empty($scope_keys))
|
| 484 |
$scope_keys = array_keys(_scope_map());
|
| 485 |
return $scope_keys[$i] ;
|
| 486 |
}
|
| 487 |
|
| 488 |
/**
|
| 489 |
* @return a long description of this numeric scope value
|
| 490 |
*/
|
| 491 |
|
| 492 |
function _get_scope_description($i = null)
|
| 493 |
{
|
| 494 |
global $scope_values ;
|
| 495 |
if (empty($scope_values))
|
| 496 |
$scope_values = array_values(_scope_map());
|
| 497 |
return $i == null ? $scope_values : $scope_values[$i] ;
|
| 498 |
}
|
| 499 |
|
| 500 |
/**
|
| 501 |
* @return a short description of this numeric scope value
|
| 502 |
*/
|
| 503 |
|
| 504 |
function _get_scope_short_description($i = null)
|
| 505 |
{
|
| 506 |
if ($i == 0) return null ;
|
| 507 |
return _get_scope_description($i);
|
| 508 |
}
|
| 509 |
|
| 510 |
|
| 511 |
/**
|
| 512 |
* Validate our forms
|
| 513 |
* @param string form id
|
| 514 |
* @param array form values
|
| 515 |
*/
|
| 516 |
function carbon_stamp_validate($form_id, $form_values)
|
| 517 |
{
|
| 518 |
for ($i = 0 ; $i < 500 ; $i++)
|
| 519 |
{
|
| 520 |
_validate_adjustment($form_id, "ff". $i .".adjustment");
|
| 521 |
_validate_date($form_id, "ff". $i .".startdate_s");
|
| 522 |
_validate_date($form_id, "ff". $i .".enddate_s");
|
| 523 |
}
|
| 524 |
}
|
| 525 |
|
| 526 |
|
| 527 |
/**
|
| 528 |
* the field is evaluated PHP so it is important not to
|
| 529 |
* allow any code to be maliciously inserted.
|
| 530 |
*/
|
| 531 |
|
| 532 |
function _validate_adjustment($form_id, $field_id)
|
| 533 |
{
|
| 534 |
$matches = array();
|
| 535 |
if (!empty($form_id->$field_id))
|
| 536 |
if (!preg_match('/^[0-9\.\*\/\+\-\(\)]*$/', $form_id->$field_id, $matches))
|
| 537 |
form_set_error($field_id, t("Only . 0-9 ( ) * / + or - accepted in 'adjustment' field"));
|
| 538 |
}
|
| 539 |
|
| 540 |
|
| 541 |
function _validate_date($form_id, $field_id)
|
| 542 |
{
|
| 543 |
$matches = array();
|
| 544 |
if (!empty($form_id->$field_id))
|
| 545 |
if (!preg_match("/^\d\d\d\d\-\d\d\-\d\d/", $form_id->$field_id, $matches))
|
| 546 |
form_set_error($field_id, t("Please check that date is in YYYY-mm-dd format."));
|
| 547 |
}
|
| 548 |
|
| 549 |
|
| 550 |
/**
|
| 551 |
* This function is called prior to carbon_stamp node_save.
|
| 552 |
*
|
| 553 |
* @param $form
|
| 554 |
* @param $form_state discovered that there is a ['values'] field.
|
| 555 |
*
|
| 556 |
*/
|
| 557 |
function carbon_stamp_submit(&$form, &$form_state)
|
| 558 |
{
|
| 559 |
$upd = 0 ;
|
| 560 |
$f = &$form_state['values'] ;
|
| 561 |
|
| 562 |
if (isset($form_state['values']['code_index']))
|
| 563 |
{
|
| 564 |
$keys = CarbonSources::getDefault()->keys();
|
| 565 |
$f['code'] = $keys[$f['code_index']]; $upd += 1;
|
| 566 |
}
|
| 567 |
if (isset($f['scope_index']))
|
| 568 |
{
|
| 569 |
$f['scope'] = $scope = $f['scope_index']; $upd += 2;
|
| 570 |
}
|
| 571 |
if (!empty($f['startdate_s']))
|
| 572 |
{
|
| 573 |
$f['startdate'] = strtotime($f['startdate_s']); $upd += 4;
|
| 574 |
}
|
| 575 |
else
|
| 576 |
{
|
| 577 |
$f['startdate'] = "" ; // remove existing date
|
| 578 |
}
|
| 579 |
|
| 580 |
if (!empty($f['enddate_s']))
|
| 581 |
{
|
| 582 |
$f['enddate'] = strtotime($f['enddate_s']); $upd += 8;
|
| 583 |
}
|
| 584 |
else
|
| 585 |
{
|
| 586 |
$f['enddate'] = $scope == 1 ? time() : CarbonDate::today(); $upd += 16;
|
| 587 |
}
|
| 588 |
// drupal_set_message('(debug) updated fields map :'.$upd, 'info');
|
| 589 |
|
| 590 |
if (!isset($f['aid_map_updated']))
|
| 591 |
{
|
| 592 |
// drupal_set_message("Unable to attach to a footprint", "info");
|
| 593 |
return ;
|
| 594 |
}
|
| 595 |
global $aid_map ; // this is yuk., assumes we have just loaded the node
|
| 596 |
if (!isset($aid_map))
|
| 597 |
$aid_map = array();
|
| 598 |
|
| 599 |
// after the editing, on checked boxed the values in
|
| 600 |
// aid_updated are set to the keys, on unchecked boxes
|
| 601 |
// the values are set to zero.
|
| 602 |
|
| 603 |
$aid_map_updated = array_flip($f['aid_map_updated']);
|
| 604 |
if (isset($aid_map_updated[0]))
|
| 605 |
unset($aid_map_updated[0]); // loose the 0 key created by any unchecked boxes
|
| 606 |
|
| 607 |
$f['aid_map'] = $aid_map ;
|
| 608 |
$f['aid_map_updated'] = $aid_map_updated ;
|
| 609 |
}
|
| 610 |
|
| 611 |
|
| 612 |
|
| 613 |
/**
|
| 614 |
* Implementation of hook_load.
|
| 615 |
* Slightly cheekily get the count of the number of footprints in the query
|
| 616 |
* stamp->aid_map[] contains account_id => title of stamp
|
| 617 |
*
|
| 618 |
* @param $node
|
| 619 |
* @return carbon_stamp
|
| 620 |
*/
|
| 621 |
|
| 622 |
function carbon_stamp_load(&$node) {
|
| 623 |
|
| 624 |
$query = db_query(
|
| 625 |
"SELECT t.* , j.fid as attached_aid, n.title as attached_title " .
|
| 626 |
"FROM {carbon_stamp} t " .
|
| 627 |
"LEFT JOIN {carbon_stamp_account} j ON t.nid = j.sid " .
|
| 628 |
"LEFT JOIN {node} n ON j.fid = n.nid " . // to get footprint title
|
| 629 |
"WHERE t.nid = %d " .
|
| 630 |
" ", $node->nid);
|
| 631 |
$first_record = null ;
|
| 632 |
global $aid_map ; $aid_map = array() ; // having to hold this array because it is being wiped.
|
| 633 |
while ($record = db_fetch_object($query))
|
| 634 |
{
|
| 635 |
if (empty($first_record))
|
| 636 |
{
|
| 637 |
$first_record = $record ;
|
| 638 |
$first_record->aid_map = array();
|
| 639 |
}
|
| 640 |
if (!empty($record->attached_aid))
|
| 641 |
$first_record->aid_map[$record->attached_aid] = $record->attached_title ;
|
| 642 |
$aid_map = $first_record->aid_map ;
|
| 643 |
}
|
| 644 |
if (empty($first_record))
|
| 645 |
drupal_set_message(t("Failed to load carbon_stamp where nid=%nid", array("%nid"=>$node->nid)));
|
| 646 |
|
| 647 |
return $first_record;
|
| 648 |
}
|
| 649 |
|
| 650 |
|
| 651 |
/**
|
| 652 |
* Implementation of hook_insert, which saves carbon-specific information
|
| 653 |
* into the carbon table
|
| 654 |
* @param node object
|
| 655 |
*/
|
| 656 |
|
| 657 |
function carbon_stamp_insert(&$node)
|
| 658 |
{
|
| 659 |
db_query("INSERT INTO {carbon_stamp} ".
|
| 660 |
"(code, scope, reading, adjustment, protection, " .
|
| 661 |
" exclude, startdate, enddate, nid) ".
|
| 662 |
"VALUES ('%s', %d, '%s', '%s', %d, %d, %d, %d, %d)",
|
| 663 |
$node->code, $node->scope, $node->reading, $node->adjustment,
|
| 664 |
$node->protection, $node->exclude, $node->startdate, $node->enddate,
|
| 665 |
$node->nid);
|
| 666 |
_update_footprint_join($node);
|
| 667 |
}
|
| 668 |
|
| 669 |
|
| 670 |
|
| 671 |
/**
|
| 672 |
* Implementation of hook_update, which saves updated todo-specific
|
| 673 |
* information into the todo table
|
| 674 |
* @param node object
|
| 675 |
*/
|
| 676 |
function carbon_stamp_update(&$node)
|
| 677 |
{
|
| 678 |
|
| 679 |
db_query("UPDATE {carbon_stamp} set code='%s',scope=%d,reading='%s',adjustment='%s',protection=%d," .
|
| 680 |
" exclude=%d, startdate=%d, enddate=%d " .
|
| 681 |
" WHERE nid=%d",
|
| 682 |
$node->code, $node->scope, $node->reading, $node->adjustment,
|
| 683 |
$node->protection, $node->exclude, $node->startdate, $node->enddate,
|
| 684 |
$node->nid);
|
| 685 |
_update_footprint_join($node);
|
| 686 |
}
|
| 687 |
|
| 688 |
/**
|
| 689 |
* the use may choose to insert and delete the stamp from different
|
| 690 |
* footprints. carbon_stamp_submit() works out which tables need
|
| 691 |
* updating. This function inserts/removes the row.
|
| 692 |
*/
|
| 693 |
|
| 694 |
|
| 695 |
function _update_footprint_join($node)
|
| 696 |
{
|
| 697 |
$node->aid_insert = array_diff(array_keys($node->aid_map_updated), array_keys($node->aid_map));
|
| 698 |
$node->aid_delete = array_diff(array_keys($node->aid_map), array_keys($node->aid_map_updated));
|
| 699 |
|
| 700 |
if (isset($node->aid_insert))
|
| 701 |
foreach ($node->aid_insert as $aid)
|
| 702 |
{
|
| 703 |
db_query("INSERT INTO {carbon_stamp_account} (sid,fid) VALUES (%d, %d)", $node->nid, $aid);
|
| 704 |
}
|
| 705 |
|
| 706 |
if (isset($node->aid_delete))
|
| 707 |
foreach ($node->aid_delete as $aid)
|
| 708 |
{
|
| 709 |
db_query("DELETE FROM {carbon_stamp_account} WHERE sid=%d AND fid=%d", $node->nid, $aid);
|
| 710 |
}
|
| 711 |
}
|
| 712 |
|
| 713 |
|
| 714 |
/**
|
| 715 |
* Implementation of hook_delete()
|
| 716 |
*/
|
| 717 |
function carbon_stamp_delete($node) {
|
| 718 |
db_query("DELETE FROM {carbon_stamp_account} WHERE sid = %d", $node->nid);
|
| 719 |
db_query("DELETE FROM {carbon_stamp} WHERE nid = %d", $node->nid);
|
| 720 |
}
|
| 721 |
|
| 722 |
|
| 723 |
/**
|
| 724 |
* Implementation of hook_view, add our node specific information
|
| 725 |
* @param node object to display
|
| 726 |
* @param boolean is this a teaser or full node?
|
| 727 |
* @param boolean is this displaying on its own page
|
| 728 |
*
|
| 729 |
*/
|
| 730 |
function carbon_stamp_view(&$node, $teaser = FALSE, $page = FALSE)
|
| 731 |
{
|
| 732 |
$node->content["stamp_view"] = array("#weight"=>0, "#value" => theme('carbon_stamp_view', $node));
|
| 733 |
return $node ;
|
| 734 |
}
|
| 735 |
|
| 736 |
|
| 737 |
function theme_carbon_stamp_view($node)
|
| 738 |
{
|
| 739 |
$header = array(
|
| 740 |
array("data" => t("a")),
|
| 741 |
array("data" => t("b"))
|
| 742 |
);
|
| 743 |
global $aid_map ;
|
| 744 |
$attached_account = '' ;
|
| 745 |
foreach ($aid_map as $aid => $title)
|
| 746 |
{
|
| 747 |
$attached_account .= l($title, "node/".$aid)." ";
|
| 748 |
}
|
| 749 |
|
| 750 |
// content variable that will be returned for display
|
| 751 |
|
| 752 |
$rows[] = array("description", $node->title);
|
| 753 |
$rows[] = array("model", $node->model);
|
| 754 |
|
| 755 |
$rows[] = array("code", $node->code. " ");
|
| 756 |
$rows[] = array("amount",$node->reading );
|
| 757 |
$rows[] = array("adjustment",$node->adjustment);
|
| 758 |
$rows[] = array("scope", _get_scope_description($node->scope));
|
| 759 |
$rows[] = array("start date", empty($node->startdate) ? "" : _format_date($node->startdate ));
|
| 760 |
|
| 761 |
$rows[] = array("end date", _format_date($node->enddate ));
|
| 762 |
//$rows[] = array("exclude", $node->exclude);
|
| 763 |
$rows[] = array("created", _format_date_time($node->created ));
|
| 764 |
$rows[] = array("changed", _format_date_time($node->changed ));
|
| 765 |
$rows[] = array("published", $node->status);
|
| 766 |
$rows[] = array("accounts attached", $attached_account);
|
| 767 |
|
| 768 |
$output = theme("table", null, $rows);
|
| 769 |
|
| 770 |
return $output;
|
| 771 |
}
|
| 772 |
|
| 773 |
/**
|
| 774 |
* Implementation of hook_view, add our node specific information
|
| 775 |
* @param node object to display
|
| 776 |
* @param boolean is this a teaser or full node?
|
| 777 |
* @param boolean is this displaying on its own page
|
| 778 |
*
|
| 779 |
*/
|
| 780 |
function carbon_stamp_edit(&$node, $teaser = FALSE, $page = FALSE)
|
| 781 |
{
|
| 782 |
// if (!user_access('view carbon footprints')) {
|
| 783 |
// return true;
|
| 784 |
// }
|
| 785 |
|
| 786 |
$node = node_prepare($node, $teaser);
|
| 787 |
$carbon_account_info = theme('carbon_stamp_table_view', $node);
|
| 788 |
$node->body .= $carbon_account_info;
|
| 789 |
$node->teaser .= $carbon_account_info;
|
| 790 |
}
|
| 791 |
|
| 792 |
|
| 793 |
|
| 794 |
function _div_wrap($wrap_class, $text)
|
| 795 |
{
|
| 796 |
return "<div class='".$wrap_class."'>".$text."</div>" ;
|
| 797 |
}
|
| 798 |
|
| 799 |
|
| 800 |
/**
|
| 801 |
* walk through an array of carbon_stamps and find
|
| 802 |
* out the earliest and latest date for the stamps
|
| 803 |
*
|
| 804 |
* @return an array containing 'first' and 'last' dates.
|
| 805 |
*/
|
| 806 |
|
| 807 |
|
| 808 |
function _stamp_date_range($ar)
|
| 809 |
{
|
| 810 |
$dateRange = array();
|
| 811 |
$dateRange['first'] = $dateRange['last'] = null ;
|
| 812 |
foreach ($ar as $stamp)
|
| 813 |
{
|
| 814 |
if ($stamp->nid == 895)
|
| 815 |
{
|
| 816 |
$ab = "gg" ;
|
| 817 |
}
|
| 818 |
if (!empty($stamp->startdate))
|
| 819 |
{
|
| 820 |
$dateRange['first'] = empty($dateRange['first']) == false ?
|
| 821 |
min($stamp->startdate, $dateRange['first']) : $stamp->startdate;
|
| 822 |
}
|
| 823 |
if (!empty($stamp->enddate))
|
| 824 |
{
|
| 825 |
$dateRange['first'] = empty($dateRange['first']) == false ?
|
| 826 |
min($stamp->enddate, $dateRange['first']) : $stamp->enddate;
|
| 827 |
$dateRange['last'] = empty($dateRange['last']) == false ?
|
| 828 |
max($stamp->enddate, $dateRange['last']) : $stamp->enddate;
|
| 829 |
}
|
| 830 |
}
|
| 831 |
return $dateRange;
|
| 832 |
}
|
| 833 |
|
| 834 |
|
| 835 |
|
| 836 |
|
| 837 |
function _select_stamps_from_preferred_sources(&$stamps)
|
| 838 |
{
|
| 839 |
$sourceWeight = new SourceWeight();
|
| 840 |
$sourceWeight->initialize();
|
| 841 |
$wstamps = array();
|
| 842 |
|
| 843 |
foreach($stamps as $stamp)
|
| 844 |
{
|
| 845 |
$w = $sourceWeight->getWeight($stamp->sourcemodel);
|
| 846 |
if ($w < 1) // if weight 1 or more means not found
|
| 847 |
$wstamps[$stamp->nid][$w] = $stamp;
|
| 848 |
else
|
| 849 |
$wstamps[$stamp->nid][] = $stamp ;
|
| 850 |
}
|
| 851 |
|
| 852 |
$selected_stamps = array();
|
| 853 |
foreach($wstamps as $nid => $stamp_ar)
|
| 854 |
{
|
| 855 |
ksort($stamp_ar); // move the lightest weighted item to be first in the list
|
| 856 |
foreach($stamp_ar as $stamp)
|
| 857 |
{
|
| 858 |
$selected_stamps[$stamp->nid] = $stamp ; // take the first stamp only
|
| 859 |
break ;
|
| 860 |
}
|
| 861 |
}
|
| 862 |
return $selected_stamps ;
|
| 863 |
}
|
| 864 |
|
| 865 |
/**
|
| 866 |
* this handles the weighting of different carbon_sources
|
| 867 |
* The admin determines the carbon sources weighting via
|
| 868 |
* settings. The first listed source is the heaviest.
|
| 869 |
*/
|
| 870 |
|
| 871 |
|
| 872 |
class SourceWeight
|
| 873 |
{
|
| 874 |
var $weighted_filters = array();
|
| 875 |
|
| 876 |
function initialize()
|
| 877 |
{
|
| 878 |
$max = 20 ;
|
| 879 |
$filter_s = variable_get("carbon_model_filter", "", $max);
|
| 880 |
if ($filter_s == "")
|
| 881 |
return ;
|
| 882 |
|
| 883 |
$filters = explode(",", $filter_s, 20);
|
| 884 |
|
| 885 |
/**
|
| 886 |
* create an array consiting of model_name => weight
|
| 887 |
*/
|
| 888 |
for ($i = 0 ; $i < count($filters) ; $i++)
|
| 889 |
{
|
| 890 |
$weight = -count($filters) + $i ;
|
| 891 |
$this->weighted_filters[trim($filters[$i])] = $weight ;
|
| 892 |
}
|
| 893 |
}
|
| 894 |
|
| 895 |
/**
|
| 896 |
* look up a sourcemodel and return a weighting for it
|
| 897 |
*/
|
| 898 |
|
| 899 |
function getWeight($sourcemodel)
|
| 900 |
{
|
| 901 |
// print_r($this->weighted_filters);
|
| 902 |
$val = $this->weighted_filters[$sourcemodel] ;
|
| 903 |
|
| 904 |
if (isset($this->weighted_filters[$sourcemodel]))
|
| 905 |
return $this->weighted_filters[$sourcemodel] ;
|
| 906 |
return 1 ;
|
| 907 |
}
|
| 908 |
}
|
| 909 |
|
| 910 |
|
| 911 |
|
| 912 |
|
| 913 |
?>
|