| pierre@0 | 1 <?php | 
| pierre@0 | 2 // $Id: ad.install,v 1.2.2.4.2.27.2.7 2009/02/17 18:56:25 jeremy Exp $ | 
| pierre@0 | 3 | 
| pierre@0 | 4 /** | 
| pierre@0 | 5  * @file | 
| pierre@0 | 6  * Advertisement module database schema. | 
| pierre@0 | 7  * | 
| pierre@0 | 8  * Copyright (c) 2005-2009. | 
| pierre@0 | 9  *   Jeremy Andrews <jeremy@tag1consulting.com>. | 
| pierre@0 | 10  */ | 
| pierre@0 | 11 | 
| pierre@0 | 12 /** | 
| pierre@0 | 13  * Ad module database schema. | 
| pierre@0 | 14  */ | 
| pierre@0 | 15 function ad_schema() { | 
| pierre@0 | 16  /** | 
| pierre@0 | 17   * The ad table stores administrative information about each ad.  The | 
| pierre@0 | 18   * actual ad itself can be found in the appropriate ad type table. | 
| pierre@0 | 19   */ | 
| pierre@0 | 20   $schema['ads'] = array( | 
| pierre@0 | 21     'description' => 'The ad table stores administrative information about each ad.  The actual ad itself can be found in the appropriate ad type table.', | 
| pierre@0 | 22     'fields' => array( | 
| pierre@0 | 23       'aid' => array( | 
| pierre@0 | 24         'type' => 'int', | 
| pierre@0 | 25         'not null' => TRUE, | 
| pierre@0 | 26         'unsigned' => TRUE, | 
| pierre@0 | 27         'default' => 0, | 
| pierre@0 | 28         'description' => 'Unique ad ID. Equals to ad nid.', | 
| pierre@0 | 29       ), | 
| pierre@0 | 30       'uid' => array( | 
| pierre@0 | 31         'type' => 'int', | 
| pierre@0 | 32         'not null' => TRUE, | 
| pierre@0 | 33         'unsigned' => TRUE, | 
| pierre@0 | 34         'default' => 0, | 
| pierre@0 | 35         'description' => 'The {users}.uid that owns this node; initially, this is the user that created it.', | 
| pierre@0 | 36       ), | 
| pierre@0 | 37       'adstatus' => array( | 
| pierre@0 | 38         'type' => 'varchar', | 
| pierre@0 | 39         'length' => 255, | 
| pierre@0 | 40         'not null' => TRUE, | 
| pierre@0 | 41         'default' => '', | 
| pierre@0 | 42         'description' => 'Ad status', | 
| pierre@0 | 43       ), | 
| pierre@0 | 44       'adtype' => array( | 
| pierre@0 | 45         'type' => 'varchar', | 
| pierre@0 | 46         'length' => 255, | 
| pierre@0 | 47         'not null' => TRUE, | 
| pierre@0 | 48         'default' => '', | 
| pierre@0 | 49         'description' => 'Ad type', | 
| pierre@0 | 50       ), | 
| pierre@0 | 51       'redirect' => array( | 
| pierre@0 | 52         'type' => 'varchar', | 
| pierre@0 | 53         'length' => 255, | 
| pierre@0 | 54         'not null' => TRUE, | 
| pierre@0 | 55         'default' => '', | 
| pierre@0 | 56         'description' => 'Ad redirect URL', | 
| pierre@0 | 57       ), | 
| pierre@0 | 58       'autoactivate' => array( | 
| pierre@0 | 59         'type' => 'int', | 
| pierre@0 | 60         'not null' => TRUE, | 
| pierre@0 | 61         'unsigned' => TRUE, | 
| pierre@0 | 62         'default' => 0, | 
| pierre@0 | 63         'description' => 'Is ad autoactivating?', | 
| pierre@0 | 64       ), | 
| pierre@0 | 65       'autoactivated' => array( | 
| pierre@0 | 66         'type' => 'int', | 
| pierre@0 | 67         'not null' => TRUE, | 
| pierre@0 | 68         'unsigned' => TRUE, | 
| pierre@0 | 69         'default' => 0, | 
| pierre@0 | 70         'description' => 'Is ad autoactivated?', | 
| pierre@0 | 71       ), | 
| pierre@0 | 72       'autoexpire' => array( | 
| pierre@0 | 73         'type' => 'int', | 
| pierre@0 | 74         'not null' => TRUE, | 
| pierre@0 | 75         'unsigned' => TRUE, | 
| pierre@0 | 76         'default' => 0, | 
| pierre@0 | 77         'description' => 'Is ad autoexpiring?', | 
| pierre@0 | 78       ), | 
| pierre@0 | 79       'autoexpired' => array( | 
| pierre@0 | 80         'type' => 'int', | 
| pierre@0 | 81         'not null' => TRUE, | 
| pierre@0 | 82         'unsigned' => TRUE, | 
| pierre@0 | 83         'default' => 0, | 
| pierre@0 | 84         'description' => 'Is ad autoexpired?', | 
| pierre@0 | 85       ), | 
| pierre@0 | 86       'activated' => array( | 
| pierre@0 | 87         'type' => 'int', | 
| pierre@0 | 88         'not null' => TRUE, | 
| pierre@0 | 89         'unsigned' => TRUE, | 
| pierre@0 | 90         'default' => 0, | 
| pierre@0 | 91         'description' => 'Is ad activated?', | 
| pierre@0 | 92       ), | 
| pierre@0 | 93       'maxviews' => array( | 
| pierre@0 | 94         'type' => 'int', | 
| pierre@0 | 95         'not null' => TRUE, | 
| pierre@0 | 96         'unsigned' => TRUE, | 
| pierre@0 | 97         'default' => 0, | 
| pierre@0 | 98         'description' => 'Maximum ad impressions', | 
| pierre@0 | 99       ), | 
| pierre@0 | 100       'maxclicks' => array( | 
| pierre@0 | 101         'type' => 'int', | 
| pierre@0 | 102         'not null' => TRUE, | 
| pierre@0 | 103         'unsigned' => TRUE, | 
| pierre@0 | 104         'default' => 0, | 
| pierre@0 | 105         'description' => 'Maximum ad clicks', | 
| pierre@0 | 106       ), | 
| pierre@0 | 107       'expired' => array( | 
| pierre@0 | 108         'type' => 'int', | 
| pierre@0 | 109         'not null' => TRUE, | 
| pierre@0 | 110         'unsigned' => TRUE, | 
| pierre@0 | 111         'default' => 0, | 
| pierre@0 | 112         'description' => 'Is ad expired?', | 
| pierre@0 | 113       ), | 
| pierre@0 | 114     ), | 
| pierre@0 | 115     'primary key' => array('aid'), | 
| pierre@0 | 116     'indexes' => array( | 
| pierre@0 | 117       'uid' => array('uid'), | 
| pierre@0 | 118       'autoactivate' => array('autoactivate'), | 
| pierre@0 | 119       'autoactivate' => array('autoactivate'), | 
| pierre@0 | 120     ), | 
| pierre@0 | 121   ); | 
| pierre@0 | 122 | 
| pierre@0 | 123  /** | 
| pierre@0 | 124   * This table counts each time a given action occurs on an ad.  Actions | 
| pierre@0 | 125   * include when the ad is viewed, clicked, enabled and disabled. | 
| pierre@0 | 126   * Statistics are collected at an hourly granularity. | 
| pierre@0 | 127   * | 
| pierre@0 | 128   * The source column is used for tracking statistics for externally | 
| pierre@0 | 129   * hosted ads. | 
| pierre@0 | 130   * | 
| pierre@0 | 131   * Actions: | 
| pierre@0 | 132   *  'view', 'click', 'enable', 'disable' | 
| pierre@0 | 133   */ | 
| pierre@0 | 134   $schema['ad_statistics'] = array( | 
| pierre@0 | 135     'description' => 'Stores ad statistics.', | 
| pierre@0 | 136     'fields' => array( | 
| pierre@0 | 137       'sid' => array( | 
| pierre@0 | 138         'type' => 'serial', | 
| pierre@0 | 139         'not null' => TRUE, | 
| pierre@0 | 140         'unsigned' => TRUE, | 
| pierre@0 | 141         'description' => 'Statistics entry ID.', | 
| pierre@0 | 142       ), | 
| pierre@0 | 143       'aid' => array( | 
| pierre@0 | 144         'type' => 'int', | 
| pierre@0 | 145         'not null' => TRUE, | 
| pierre@0 | 146         'unsigned' => TRUE, | 
| pierre@0 | 147         'default' => 0, | 
| pierre@0 | 148         'description' => 'Ad id.', | 
| pierre@0 | 149       ), | 
| pierre@0 | 150       'date' => array( | 
| pierre@0 | 151         'type' => 'int', | 
| pierre@0 | 152         'not null' => TRUE, | 
| pierre@0 | 153         'unsigned' => TRUE, | 
| pierre@0 | 154         'default' => 0, | 
| pierre@0 | 155         'description' => 'Date when action was made.', | 
| pierre@0 | 156       ), | 
| pierre@0 | 157       'action' => array( | 
| pierre@0 | 158         'type' => 'varchar', | 
| pierre@0 | 159         'length' => 255, | 
| pierre@0 | 160         'not null' => TRUE, | 
| pierre@0 | 161         'default' => '', | 
| pierre@0 | 162         'description' => 'Actions: "view", "click", "enable", "disable".', | 
| pierre@0 | 163       ), | 
| pierre@0 | 164       'adgroup' => array( | 
| pierre@0 | 165         'type' => 'varchar', | 
| pierre@0 | 166         'length' => 255, | 
| pierre@0 | 167         'not null' => FALSE, | 
| pierre@0 | 168         'default' => '', | 
| pierre@0 | 169         'description' => 'Ad group.', | 
| pierre@0 | 170       ), | 
| pierre@0 | 171       'hostid' => array( | 
| pierre@0 | 172         'type' => 'varchar', | 
| pierre@0 | 173         'length' => 32, | 
| pierre@0 | 174         'not null' => TRUE, | 
| pierre@0 | 175         'default' => '', | 
| pierre@0 | 176         'description' => 'Host from which acion was made.', | 
| pierre@0 | 177       ), | 
| pierre@0 | 178       'count' => array( | 
| pierre@0 | 179         'type' => 'int', | 
| pierre@0 | 180         'not null' => TRUE, | 
| pierre@0 | 181         'unsigned' => TRUE, | 
| pierre@0 | 182         'default' => 0, | 
| pierre@0 | 183         'description' => 'Count of actions triggered.', | 
| pierre@0 | 184       ), | 
| pierre@0 | 185     ), | 
| pierre@0 | 186     'primary key' => array('sid'), | 
| pierre@0 | 187     'indexes' => array( | 
| pierre@0 | 188       'aid' => array('aid'), | 
| pierre@0 | 189       'date' => array('date'), | 
| pierre@0 | 190       'action' => array('action'), | 
| pierre@0 | 191       'adgroup' => array('adgroup'), | 
| pierre@0 | 192       'hostid' => array('hostid'), | 
| pierre@0 | 193     ), | 
| pierre@0 | 194   ); | 
| pierre@0 | 195 | 
| pierre@0 | 196  /** | 
| pierre@0 | 197   * The ad_clicks table tracks when a given advertisement was clicked, | 
| pierre@0 | 198   * who clicked it (uid if any and IP address), and what page they were | 
| pierre@0 | 199   * on when they clicked it. | 
| pierre@0 | 200   */ | 
| pierre@0 | 201   $schema['ad_clicks'] = array( | 
| pierre@0 | 202     'description' => 'The ad_clicks table tracks when a given advertisement was clicked, who clicked it (uid if any and IP address), and what page they were on when they clicked it.', | 
| pierre@0 | 203     'fields' => array( | 
| pierre@0 | 204       'cid' => array( | 
| pierre@0 | 205         'type' => 'serial', | 
| pierre@0 | 206         'not null' => TRUE, | 
| pierre@0 | 207         'unsigned' => TRUE, | 
| pierre@0 | 208         'description' => 'Statistics entry ID.', | 
| pierre@0 | 209       ), | 
| pierre@0 | 210       'aid' => array( | 
| pierre@0 | 211         'type' => 'int', | 
| pierre@0 | 212         'not null' => TRUE, | 
| pierre@0 | 213         'unsigned' => TRUE, | 
| pierre@0 | 214         'default' => 0, | 
| pierre@0 | 215         'description' => 'Ad id.', | 
| pierre@0 | 216       ), | 
| pierre@0 | 217       'uid' => array( | 
| pierre@0 | 218         'type' => 'int', | 
| pierre@0 | 219         'not null' => TRUE, | 
| pierre@0 | 220         'unsigned' => TRUE, | 
| pierre@0 | 221         'default' => 0, | 
| pierre@0 | 222         'description' => '', | 
| pierre@0 | 223       ), | 
| pierre@0 | 224       'status' => array( | 
| pierre@0 | 225         'type' => 'int', | 
| pierre@0 | 226         'size' => 'tiny', | 
| pierre@0 | 227         'not null' => TRUE, | 
| pierre@0 | 228         'unsigned' => TRUE, | 
| pierre@0 | 229         'default' => 0, | 
| pierre@0 | 230         'description' => '', | 
| pierre@0 | 231       ), | 
| pierre@0 | 232       'hostname' => array( | 
| pierre@0 | 233         'type' => 'varchar', | 
| pierre@0 | 234         'length' => 128, | 
| pierre@0 | 235         'not null' => TRUE, | 
| pierre@0 | 236         'default' => '', | 
| pierre@0 | 237         'description' => 'Host from which acion was made.', | 
| pierre@0 | 238       ), | 
| pierre@0 | 239       'user_agent' => array( | 
| pierre@0 | 240         'type' => 'varchar', | 
| pierre@0 | 241         'length' => 255, | 
| pierre@0 | 242         'not null' => TRUE, | 
| pierre@0 | 243         'default' => '', | 
| pierre@0 | 244         'description' => 'Clicker\'s browser agent.', | 
| pierre@0 | 245       ), | 
| pierre@0 | 246       'adgroup' => array( | 
| pierre@0 | 247         'type' => 'varchar', | 
| pierre@0 | 248         'length' => 255, | 
| pierre@0 | 249         'not null' => TRUE, | 
| pierre@0 | 250         'default' => '', | 
| pierre@0 | 251         'description' => 'Ad group.', | 
| pierre@0 | 252       ), | 
| pierre@0 | 253       'hostid' => array( | 
| pierre@0 | 254         'type' => 'varchar', | 
| pierre@0 | 255         'length' => 32, | 
| pierre@0 | 256         'not null' => TRUE, | 
| pierre@0 | 257         'default' => '', | 
| pierre@0 | 258         'description' => 'Host from which acion was made.', | 
| pierre@0 | 259       ), | 
| pierre@0 | 260       'url' => array( | 
| pierre@0 | 261         'type' => 'varchar', | 
| pierre@0 | 262         'length' => 255, | 
| pierre@0 | 263         'not null' => FALSE, | 
| pierre@0 | 264         'default' => '', | 
| pierre@0 | 265         'description' => 'Clicked URL.', | 
| pierre@0 | 266       ), | 
| pierre@0 | 267       'timestamp' => array( | 
| pierre@0 | 268         'type' => 'int', | 
| pierre@0 | 269         'not null' => TRUE, | 
| pierre@0 | 270         'unsigned' => TRUE, | 
| pierre@0 | 271         'default' => 0, | 
| pierre@0 | 272         'description' => 'Date when action was made.', | 
| pierre@0 | 273       ), | 
| pierre@0 | 274     ), | 
| pierre@0 | 275     'primary key' => array('cid'), | 
| pierre@0 | 276     'indexes' => array( | 
| pierre@0 | 277       'aid' => array('aid'), | 
| pierre@0 | 278       'status' => array('status'), | 
| pierre@0 | 279       'hostname' => array('hostname'), | 
| pierre@0 | 280       'user_agent' => array('user_agent'), | 
| pierre@0 | 281       'adgroup' => array('adgroup'), | 
| pierre@0 | 282       'hostid' => array('hostid'), | 
| pierre@0 | 283       'url' => array('url'), | 
| pierre@0 | 284     ), | 
| pierre@0 | 285   ); | 
| pierre@0 | 286 | 
| pierre@0 | 287  /** | 
| pierre@0 | 288   * The ad_hosts table is used to configure users that can display ads | 
| pierre@0 | 289   * remotely. | 
| pierre@0 | 290   */ | 
| pierre@0 | 291   $schema['ad_hosts'] = array( | 
| pierre@0 | 292     'description' => 'The ad_hosts table is used to configure users that can display ads remotely. ', | 
| pierre@0 | 293     'fields' => array( | 
| pierre@0 | 294       'uid' => array( | 
| pierre@0 | 295         'type' => 'int', | 
| pierre@0 | 296         'not null' => TRUE, | 
| pierre@0 | 297         'unsigned' => TRUE, | 
| pierre@0 | 298         'default' => 0, | 
| pierre@0 | 299         'description' => '', | 
| pierre@0 | 300       ), | 
| pierre@0 | 301       'hostid' => array( | 
| pierre@0 | 302         'type' => 'varchar', | 
| pierre@0 | 303         'length' => 32, | 
| pierre@0 | 304         'not null' => TRUE, | 
| pierre@0 | 305         'default' => '', | 
| pierre@0 | 306         'description' => 'Host from which acion was made.', | 
| pierre@0 | 307       ), | 
| pierre@0 | 308       'status' => array( | 
| pierre@0 | 309         'type' => 'int', | 
| pierre@0 | 310         'size' => 'tiny', | 
| pierre@0 | 311         'not null' => TRUE, | 
| pierre@0 | 312         'unsigned' => TRUE, | 
| pierre@0 | 313         'default' => 0, | 
| pierre@0 | 314         'description' => '', | 
| pierre@0 | 315       ), | 
| pierre@0 | 316       'description' => array( | 
| pierre@0 | 317         'type' => 'text', | 
| pierre@0 | 318         'not null' => FALSE, | 
| pierre@0 | 319         'description' => 'Host from which acion was made.', | 
| pierre@0 | 320       ), | 
| pierre@0 | 321     ), | 
| pierre@0 | 322     'primary key' => array('uid'), | 
| pierre@0 | 323     'indexes' => array( | 
| pierre@0 | 324       'status' => array('status'), | 
| pierre@0 | 325       'hostid' => array('hostid'), | 
| pierre@0 | 326     ), | 
| pierre@0 | 327   ); | 
| pierre@0 | 328 | 
| pierre@0 | 329   return $schema; | 
| pierre@0 | 330 } | 
| pierre@0 | 331 | 
| pierre@0 | 332 /** | 
| pierre@0 | 333  * Ad module installation. | 
| pierre@0 | 334  */ | 
| pierre@0 | 335 function ad_install() { | 
| pierre@0 | 336   // Create tables. | 
| pierre@0 | 337   drupal_install_schema('ad'); | 
| pierre@0 | 338 } | 
| pierre@0 | 339 | 
| pierre@0 | 340 /** | 
| pierre@0 | 341  * Allow complete uninstallation of the ad module. | 
| pierre@0 | 342  */ | 
| pierre@0 | 343 function ad_uninstall() { | 
| pierre@0 | 344   // Remove tables. | 
| pierre@0 | 345   drupal_uninstall_schema('ad'); | 
| pierre@0 | 346 | 
| pierre@0 | 347   // Delete all ad content. | 
| pierre@0 | 348   $result = db_query("SELECT nid FROM {node} WHERE type = 'ad'"); | 
| pierre@0 | 349   while ($node = db_fetch_object($result)) { | 
| pierre@0 | 350     node_delete($node->nid); | 
| pierre@0 | 351     variable_del("ad_autoactivate_warning_$node->nid"); | 
| pierre@0 | 352   } | 
| pierre@0 | 353 | 
| pierre@0 | 354   // Delete all remaining ad module variables. | 
| pierre@0 | 355   $variables = array('ad_cron_timestamp', 'ad_link_target', 'ad_cache', 'ad_cache_file', 'adserve', 'ad_group_vid', 'ad_groups', 'ad_validate_url', 'ad_display'); | 
| pierre@0 | 356   foreach ($variables as $variable) { | 
| pierre@0 | 357     variable_del($variable); | 
| pierre@0 | 358   } | 
| pierre@0 | 359   db_query("DELETE FROM {variable} WHERE name LIKE 'ad_block_quantity_%'"); | 
| pierre@0 | 360 } | 
| pierre@0 | 361 | 
| pierre@0 | 362 /** | 
| pierre@0 | 363  * Convert some things from absolete dev. schema to new schema API | 
| pierre@0 | 364  */ | 
| pierre@0 | 365 function ad_update_6001() { | 
| pierre@0 | 366   $ret = array(); | 
| pierre@0 | 367   // When we touching index columns, we should first remove it from schema | 
| pierre@0 | 368   db_drop_index($ret, 'ad_clicks', 'status'); | 
| pierre@0 | 369   db_change_field($ret, 'ad_clicks', 'status', 'status', | 
| pierre@0 | 370       array( | 
| pierre@0 | 371         'type' => 'int', | 
| pierre@0 | 372         'size' => 'tiny', | 
| pierre@0 | 373         'not null' => TRUE, | 
| pierre@0 | 374         'unsigned' => TRUE, | 
| pierre@0 | 375         'default' => 0, | 
| pierre@0 | 376         'description' => '', | 
| pierre@0 | 377       ), | 
| pierre@0 | 378       array('indexes' => array( | 
| pierre@0 | 379         'status' => array('status'), | 
| pierre@0 | 380       ), | 
| pierre@0 | 381     ) | 
| pierre@0 | 382   ); | 
| pierre@0 | 383   db_drop_index($ret, 'ad_hosts', 'status'); | 
| pierre@0 | 384   db_change_field($ret, 'ad_hosts', 'status', 'status', | 
| pierre@0 | 385       array( | 
| pierre@0 | 386         'type' => 'int', | 
| pierre@0 | 387         'size' => 'tiny', | 
| pierre@0 | 388         'not null' => TRUE, | 
| pierre@0 | 389         'unsigned' => TRUE, | 
| pierre@0 | 390         'default' => 0, | 
| pierre@0 | 391         'description' => '', | 
| pierre@0 | 392       ), | 
| pierre@0 | 393       array('indexes' => array( | 
| pierre@0 | 394         'status' => array('status'), | 
| pierre@0 | 395       ), | 
| pierre@0 | 396     ) | 
| pierre@0 | 397   ); | 
| pierre@0 | 398 | 
| pierre@0 | 399   db_drop_index($ret, 'ad_statistics', 'hostid'); | 
| pierre@0 | 400   db_change_field($ret, 'ad_statistics', 'hostid', 'hostid', | 
| pierre@0 | 401       array( | 
| pierre@0 | 402         'type' => 'varchar', | 
| pierre@0 | 403         'length' => 32, | 
| pierre@0 | 404         'not null' => TRUE, | 
| pierre@0 | 405         'default' => '', | 
| pierre@0 | 406         'description' => 'Host from which acion was made.', | 
| pierre@0 | 407       ), | 
| pierre@0 | 408       array('indexes' => array( | 
| pierre@0 | 409         'hostid' => array('hostid'), | 
| pierre@0 | 410       ), | 
| pierre@0 | 411     ) | 
| pierre@0 | 412   ); | 
| pierre@0 | 413 | 
| pierre@0 | 414   db_drop_index($ret, 'ad_hosts', 'hostid'); | 
| pierre@0 | 415   db_change_field($ret, 'ad_hosts', 'hostid', 'hostid', | 
| pierre@0 | 416       array( | 
| pierre@0 | 417         'type' => 'varchar', | 
| pierre@0 | 418         'length' => 32, | 
| pierre@0 | 419         'not null' => TRUE, | 
| pierre@0 | 420         'default' => '', | 
| pierre@0 | 421         'description' => 'Host from which acion was made.', | 
| pierre@0 | 422       ), | 
| pierre@0 | 423       array('indexes' => array( | 
| pierre@0 | 424         'hostid' => array('hostid'), | 
| pierre@0 | 425       ), | 
| pierre@0 | 426     ) | 
| pierre@0 | 427   ); | 
| pierre@0 | 428   return $ret; | 
| pierre@0 | 429 } | 
| pierre@0 | 430 | 
| pierre@0 | 431 /** | 
| pierre@0 | 432  * Rebuild menu for anyone using the ad_embed module. | 
| pierre@0 | 433  */ | 
| pierre@0 | 434 function ad_update_6002() { | 
| pierre@0 | 435   menu_rebuild(); | 
| pierre@0 | 436   return array(); | 
| pierre@0 | 437 } | 
| pierre@0 | 438 | 
| pierre@0 | 439 /** | 
| pierre@0 | 440  * Flush all caches for new themeable ad display functions. | 
| pierre@0 | 441  */ | 
| pierre@0 | 442 function ad_update_6003() { | 
| pierre@0 | 443   drupal_flush_all_caches(); | 
| pierre@0 | 444   return array(); | 
| pierre@0 | 445 } |