ed_classified_utils.inc in Classified Ads 5.2
Same filename and directory in other branches
Simple text-based classified ads module. Michael Curry, Exodus Development, Inc. exodusdev@gmail.com for more information, please visit http://exodusdev.com/drupal/modules/classified.module Copyright (c) 2006, 2007 Exodus Development, Inc. All Rights Reserved. Licensed under the terms of the GNU Public License (GPL) version 2. Please see LICENSE.txt for license terms. Possession and use of this code signifies acceptance of license terms.
File
ed_classified_utils.incView source
<?php
/**
* @file
* Simple text-based classified ads module.
* Michael Curry, Exodus Development, Inc.
* exodusdev@gmail.com
* for more information, please visit http://exodusdev.com/drupal/modules/classified.module
* Copyright (c) 2006, 2007 Exodus Development, Inc. All Rights Reserved.
* Licensed under the terms of the GNU Public License (GPL) version 2. Please see LICENSE.txt for
* license terms. Possession and use of this code signifies acceptance of license
* terms.
*/
/**
* taxonomy_vocabulary_load() is in Drupal 6, not Drupal 5
*/
if (!function_exists('taxonomy_vocabulary_load')) {
function taxonomy_vocabulary_load($vid) {
// Drupal 5
return taxonomy_get_vocabulary(_ed_classified_get_vid());
}
}
/**
* config variable helpers
*/
function _ed_classified_cfg_varname($name) {
// ensure unique varnames for this module
return EDI_CLASSIFIED_MODULE_NAME . '_' . $name;
}
function _ed_classified_variable_get($name, $defval, $log = FALSE) {
$val = variable_get(_ed_classified_cfg_varname($name), $defval);
if ($log) {
_edi_wd(sprintf('variable_get \'%s\'= \'%s\'', _ed_classified_cfg_varname($name), $val));
}
return $val;
}
function _ed_classified_variable_set($name, $newval, $log = FALSE) {
if ($log) {
_edi_wd(sprintf('variable_set \'%s\' changed from \'%s\' to \'%s\'', _ed_classified_cfg_varname($name), _ed_classified_variable_get($name, ''), $newval));
}
variable_set(_ed_classified_cfg_varname($name), $newval);
}
/**
* Convert db_query results to an array
*/
function _ed_classified_query_results_to_array($qr) {
$arr = array();
while ($info = db_fetch_object($qr)) {
$arr[] = $info;
}
return $arr;
}
/**
* Helper function to determine the single ad category name to which this node belongs.
*/
function _ed_classified_get_primary_category($node) {
// lifted from _nodeapi implementation - crude, need to find out if there's a better way to get the single term for this node.
$terms = taxonomy_node_get_terms_by_vocabulary($node, _ed_classified_get_vid());
$term = array_pop($terms);
if ($term) {
$vocabulary = taxonomy_vocabulary_load(_ed_classified_get_vid());
if ($parents = taxonomy_get_parents_all($term->tid)) {
return $parents[0];
}
}
return 0;
}
/**
* convert days to # seconds
*/
function _ed_classified_days_to_seconds($days) {
return $days * 86400;
// 60 * 60 * 24 = 86400
}
/**
* Is a node really a classified ad?
*/
function _ed_classified_node_is_classified($node) {
return EDI_CLASSIFIED_MODULE_NAME == $node->type;
}
/**
* Is a tid a 'classified' term? Is a tid a child of our taxonomy?
* @param $tid The term id to check.
* @return true if the term is a child of our vocabulary.
*/
function _ed_tid_is_classified_term($tid) {
$vid = _ed_classified_get_vid();
$vocab = taxonomy_vocabulary_load($vid);
$term = taxonomy_get_term($tid);
if ($vocab->hierarchy && $vocab->module == EDI_CLASSIFIED_MODULE_NAME) {
return $term->vid == $vid;
}
else {
//
// TODO: warn user about problems in a non-log-filling way.
// _edi_wd(t('Internal error: Vocabulary !vid (@vocab_name) is not our dedicated classified ads vocabulary - someone has tampered with the vocabulary, or our stored variables.', array('!vid' => $vid, '@vocab_name' => $vocab->name)), WATCHDOG_ERROR);
return FALSE;
// sanity check: not possible since the vocab is not hierarchical or is not our vocabulary
}
}
/**
* Get default ad duration in seconds
*/
function _ed_classified_get_default_ad_duration_in_seconds() {
$duration = _ed_classified_days_to_seconds(_ed_classified_variable_get('default_ad_duration', EDI_CLASSIFIED_VAR_DEF_EXPIRATION_DAYS));
return $duration;
}
/**
* Find the longest duration, in days, for a given set of terms
* @param $terms, an array of vid/tid pairs with vid as the key
* sub-arrays are allowed, for example:
* Array = (
* [63]=>5,
* [10]=> Array ([0]=>234, [1]=>984)
* )
* equivalent to:
* Array = (
* [63]=>5,
* [10]=>234,
* [10]=>984
* )
* @return the duration, in days, of the largest duration found.
*/
function _ed_classified_get_longest_duration($terms) {
$duration = 0;
if (!empty($terms)) {
// Normally we expect an array of taxonomy terms
if (is_array($terms)) {
reset($terms);
while (list($key, $val) = each($terms)) {
if (is_array($val)) {
reset($val);
while (list($subkey, $subval) = each($val)) {
$d = _ed_classified_get_duration(array(
$key => $subval,
));
if ($d > $duration) {
$duration = $d;
}
}
}
else {
$d = _ed_classified_get_duration(array(
$key => $val,
));
if ($d > $duration) {
$duration = $d;
}
}
}
}
}
// If we couldn't find a duration then set to default rather than zero
if (0 == $duration) {
$duration = _ed_classified_get_default_ad_duration_in_seconds();
}
return $duration;
}
/**
* Get stats
*/
function ed_classified_get_ad_stats() {
return theme('ed_classified_ads_stats');
}
function ed_classified_get_adcount($only_published) {
$status = '';
if ($only_published) {
$status = 'status=1 AND';
}
$qr = db_query("SELECT COUNT(nid) as c FROM {node} WHERE " . $status . " type='ed_classified';");
$o = db_fetch_object($qr);
return $o->c;
}
/**
* Get ad count for time range
*/
function ed_classified_get_adcount_for_time_range($start_time, $end_time, $only_published) {
$status = '';
if ($only_published) {
$status = 'status=1 AND';
}
$qr = db_query("SELECT COUNT(nid) as c FROM {node} WHERE " . $status . " type='ed_classified' AND created >= %d AND created <=%d;", $start_time, $end_time);
$o = db_fetch_object($qr);
return $o->c;
}
/**
* Get a list of popular ads for block use
*/
function ed_classified_get_popular_ads_list() {
$output = '';
$have_statistics = _ed_classified_module_exists('statistics');
if ($have_statistics) {
$q = db_query_range(db_rewrite_sql("SELECT n.nid, n.title, n.created, n.changed, s.totalcount as counter FROM {node_counter} s INNER JOIN {node} n ON s.nid = n.nid WHERE n.status = 1 AND n.type = '%s' ORDER BY s.totalcount,n.nid, n.title, n.created, n.changed DESC", '{node_counter}', 'nid', EDI_CLASSIFIED_MODULE_NAME), 0, _ed_classified_variable_get('block_popular_limit', 4));
$output = theme('ed_classified_ads_block', _ed_classified_query_results_to_array($q), FALSE, TRUE, TRUE);
}
return $output;
}
/**
* Get a list of latest ads for block use
*/
function ed_classified_get_latest_ads_list() {
// Show recent nodes, but only if they haven't expired
$q = db_query_range(db_rewrite_sql("SELECT n.title, n.nid, n.created AS timestamp, n.changed FROM {node} AS n, {edi_classified_nodes} AS ec WHERE n.type = \\'ed_classified\\' AND n.status = 1 AND n.nid = ec.nid AND n.vid = ec.vid AND ec.expires_on > '%d' ORDER BY n.created,n.title, n.nid DESC", 'n', 'nid', REQUEST_TIME), 0, _ed_classified_variable_get('block_latest_limit', 4));
return theme('ed_classified_ads_block', _ed_classified_query_results_to_array($q), TRUE, FALSE, TRUE);
}
/**
* expire old ads
*/
function _ed_classified_expire_ads($time) {
// mark ads matching criteria. Set $node->status=>unpublished,
$query = _ed_classified_get_aged_ads(0, $time, 1);
// get published but old ads
while ($node = db_fetch_object($query)) {
_ed_classified_unpublish_ad($node->nid);
_ed_classified_notify_user_of_ad_expiration($node);
}
}
/**
* Get a query result with any ads that have expired prior to a given date, and having a specific publish status
*/
function _ed_classified_get_aged_ads($expire_time_start, $expire_time_end, $status = 1) {
return db_query("SELECT * FROM {node} n, {edi_classified_nodes} ec WHERE n.type='ed_classified' AND n.vid = ec.vid AND n.status = %d AND (ec.expires_on >= %d AND ec.expires_on <= %d)", $status, $expire_time_start, $expire_time_end);
}
/**
* Get the expiration date of a classified ad node
*/
function ed_classified_get_ad_expiration($node) {
$expires = 0;
// TODO: need windows-compatible old date - use time()?
$q = db_query("SELECT expires_on FROM {edi_classified_nodes} ecn WHERE ecn.nid = '%d' AND ecn.vid = '%d'", $node->nid, $node->vid);
if ($q) {
$expires = db_result($q);
}
return $expires;
}
/**
* Get settings 'banner'
*/
function _ed_classified_settings_get_banner(&$form) {
$name = EDI_CLASSIFIED_MODULE_NAME;
$d = '<a target="_blank" href="https://www.paypal.com/cgi-bin/webscr?cmd=_xclick&business=exodus.paypal%40gmail.com&item_name=' . $name . '&item_number= ' . $name . '-donation&page_style=PayPal&no_shipping=1&return=http%3A%2F%2Fexodusdev.com%2Fproducts&cancel_return=http%3A%2F%2Fexodusdev.com%2Fproducts&no_note=1&tax=0¤cy_code=USD&lc=US&bn=PP%2dDonationsBF&charset=UTF%2d8"><img src="http://www.paypal.com/en_US/i/btn/x-click-but7.gif" alt="Support ongoing development!" title="Support ongoing development!"></a>';
$form['module_banner'] = array(
'#type' => 'markup',
'#value' => '<div style="border: solid 1px #eee; margin: .5em; padding: .5em;"><div style="float:right;">' . $d . '</div><strong>Module development by <a href="http://exodusdev.com">Exodus Development</a></strong>.<br/>',
);
$form['module_id'] = array(
'#type' => 'markup',
'#value' => EDI_CLASSIFIED_MODULE_VERSION . '<br/></div>',
);
}
/**
* do the sanity-check dance.
*/
function _ed_classified_check_settings(&$form) {
$vid = _ed_classified_get_vid();
$taxonomy = taxonomy_get_tree($vid);
$warning = "";
if (empty($taxonomy)) {
if (!empty($vid)) {
$url = "admin/content/taxonomy/{$vid}/add/term";
$url = _edi_l('taxonomy administration', $url);
$warning = t('<div class="error">It appears that you have not configured any vocabulary terms to be used with the Classified Ads module. This module will not function correctly until you define vocabulary terms for vocabulary id !vid. Please visit !url to add terms such as "For Sale" or "Wanted" (or other categories as appropriate for your needs).</div>', array(
'!url' => $url,
'!vid' => $vid,
));
}
else {
$url = 'http://exodusdev.com/drupal/modules/ed_classified.module';
$url = _edi_l('the project homepage', $url);
$warning = t('<div class="error">The classified ads vocabulary settings are not configured correctly. This is mostly likely due to a failed installation or an administrator deleting the automatically configured taxonomy or other problems. Please visit the online handbook page(s) at !url.</div>', array(
'!url' => $url,
));
}
$form['warning'] = array(
'#type' => 'markup',
'#value' => $warning,
);
return FALSE;
}
return TRUE;
}
/**
* Get just the raw text describing expiration date
*/
function _ed_classified_get_ending_date_string($ad_expiration_date) {
// TODO: get time string for how long ago expired
$interval = $ad_expiration_date - REQUEST_TIME;
$expired = FALSE;
if ($interval < 0) {
$interval = -$interval;
$expired = TRUE;
}
$str = '';
if ($ad_expiration_date != 0) {
$str = sprintf(t('%s on %s (%s%s)'), $expired ? t('expired') : t('expires'), format_date($ad_expiration_date), format_interval($interval, 2), $expired ? t(' ago') : '');
}
return $str;
}
/**
* Helper function: does $expiration date expire "soon" (soon depends on who you ask)
*/
function _ed_classified_ad_expires_soon($expiration_date) {
return $expiration_date - REQUEST_TIME > 0 && $expiration_date - REQUEST_TIME < _ed_classified_days_to_seconds(3);
// TODO: use config var
}
/**
* return true if ad has expired
*/
function _ed_classified_ad_expired_already($expiration_date) {
return $expiration_date <= REQUEST_TIME;
}
/**
* Returns (and possibly creates) a primary vocabulary for classified
* Repairs association with primary vocabulary if $detect is TRUE.
*/
function _ed_classified_get_vid($detect = FALSE) {
$vid = _ed_classified_variable_get('vocabulary', '');
if ($detect || empty($vid)) {
$taxonomy_name = _ed_classified_displayname() . t(' Category');
// Check to see if classified ads vocabulary exists
$dbvid = db_result(db_query("SELECT vid FROM {vocabulary} WHERE module='%s'", EDI_CLASSIFIED_MODULE_NAME));
if ($dbvid != $vid) {
_edi_wd(t('Classified Ads vocabulary was not remembered but detected - storing.'));
_ed_classified_variable_set('vocabulary', $vid = $dbvid);
}
if (empty($vid)) {
// Perhaps we're just not associated, look for vocabulary by name
$dbvid = db_result(db_query("SELECT vid FROM {vocabulary} WHERE name='%s'", $taxonomy_name));
if ($dbvid) {
db_query("UPDATE {vocabulary} SET module='%s' WHERE vid='%d'", EDI_CLASSIFIED_MODULE_NAME, $vid);
_edi_wd(t('Classified Ads vocabulary was detected - associating and storing.'));
_ed_classified_variable_set('vocabulary', $vid = $dbvid);
}
}
if (empty($vid)) {
// No, still no vocabulary, we're creating it
switch (reset(explode('.', DRUPAL_VERSION))) {
case 5:
case 6:
$vid = db_result(db_query("SELECT vid FROM {vocabulary} WHERE module='%s'", ED_CLASSIFIED_MODULE_NAME));
if (!$vid) {
$vocabulary = array(
'name' => _ed_classified_displayname() . t(' Category'),
'description' => t('Vocabulary required by Classified Ads (' . ED_CLASSIFIED_MODULE_NAME . ') module. <strong>Warning: You should not delete this vocabulary unless you intend to uninstall (or have already uninstalled) the Classified Ads module.</strong>'),
'multiple' => '0',
'required' => '1',
'hierarchy' => '1',
'relations' => '0',
'module' => ED_CLASSIFIED_MODULE_NAME,
'nodes' => array(
ED_CLASSIFIED_MODULE_NAME => 1,
),
);
taxonomy_save_vocabulary($vocabulary);
$vid = $vocabulary['vid'];
$term = array();
$term['name'] = 'For sale';
$term['description'] = 'Items for sale';
$term['vid'] = $vid;
$term['weight'] = 0;
taxonomy_save_term($term);
$term['name'] = 'Wanted';
$term['description'] = 'Wanted items';
taxonomy_save_term($term);
}
_ed_classified_variable_set('vocabulary', $vid);
$msg = t('Install: Classified Ad vocabulary !vid and default terms created.', array(
'!vid' => $vid,
));
_edi_wd($msg);
drupal_set_message($msg);
break;
case 7:
$vid = db_result(db_query("SELECT vid FROM {taxonomy_vocabulary} WHERE module='%s'", ED_CLASSIFIED_MODULE_NAME));
if (!$vid) {
$vocabulary = (object) array(
'name' => 'Classified Ad Category',
'description' => t('Vocabulary required by Classified Ads (' . ED_CLASSIFIED_MODULE_NAME . ') module. <strong>Warning: You should not delete this vocabulary unless you intend to uninstall (or have already uninstalled) the Classified Ads module.</strong>'),
'multiple' => '0',
'required' => '1',
'hierarchy' => '1',
'relations' => '0',
'module' => ED_CLASSIFIED_MODULE_NAME,
'nodes' => array(
ED_CLASSIFIED_MODULE_NAME => 1,
),
);
taxonomy_vocabulary_save($vocabulary);
$vid = db_result(db_query("SELECT vid FROM {taxonomy_vocabulary} WHERE module='%s'", ED_CLASSIFIED_MODULE_NAME));
// TODO - create default terms in a Drupal 7 manner
}
_ed_classified_variable_set('vocabulary', $vid);
$msg = t('Install: Classified Ad vocabulary !vid created.', array(
'!vid' => $vid,
));
_edi_wd($msg);
drupal_set_message($msg);
break;
default:
drupal_set_message('Unknown Drupal version - unable to initialise vocabulary.');
break;
}
}
if (!empty($vid)) {
// Check that the Classified Ads vocabulary is associated with ed_classified
$dbvid = db_result(db_query("SELECT vid FROM {vocabulary_node_types} WHERE vid='%d' AND type='%s'", $vid, EDI_CLASSIFIED_MODULE_NAME));
if (empty($dbvid)) {
// Association not found
db_query("INSERT INTO {vocabulary_node_types} (vid, type) VALUES ('%d', '%s')", $vid, EDI_CLASSIFIED_MODULE_NAME);
_edi_wd(t('Classified Ads vocabulary - associating and storing.'));
}
}
else {
_edi_wd(t('Classified Ads vocabulary - not found!'));
}
}
return $vid;
}
/**
* Make a 'path' to a category view for a given tid.
*/
function _ed_classified_make_category_path($tid) {
return drupal_get_path_alias(EDI_CLASSIFIED_PATH_NAME . '/tid/' . $tid);
}
/**
* Determine, in a version-friendly way, if a module exists.
* some folks have decided to change module_exist() to module_exists() for 4.8/5.0. see: http://drupal.org/node/79601
*/
function _ed_classified_module_exists($module) {
$module_exists = FALSE;
if (function_exists('module_exist')) {
$module_exists = module_exist($module);
}
// 4.7
if (function_exists('module_exists')) {
$module_exists = module_exists($module);
}
// 4.8/5.0?
return $module_exists;
}
/**
* front end to l() due to differences between D5 & D6 causes pain
* Take D6 params but down convert to D5 if need be
*/
function _edi_l($text, $path, $options = array()) {
switch (reset(explode('.', DRUPAL_VERSION))) {
case 5:
if (empty($options)) {
return l($text, $path);
}
else {
$d5options = array();
$d5options['attributes'] = isset($options['attributes']) ? $options['attributes'] : array();
$d5options['query'] = isset($options['query']) ? $options['query'] : NULL;
$d5options['fragment'] = isset($options['fragment']) ? $options['fragment'] : NULL;
$d5options['absolute'] = isset($options['absolute']) ? $options['absolute'] : FALSE;
$d5options['html'] = isset($options['html']) ? $options['html'] : FALSE;
return l($text, $path, $d5options['attributes'], $d5options['query'], $d5options['fragment'], $d5options['absolute'], $d5options['html']);
}
break;
case 6:
case 7:
return l($text, $path, $options);
break;
}
}
/**
* shortcut - log something to the watchdog log
*/
function _edi_wd($message, $severity = WATCHDOG_NOTICE, $link = NULL) {
switch (reset(explode('.', DRUPAL_VERSION))) {
case 5:
watchdog(EDI_CLASSIFIED_MODULE_NAME, $message, $severity, $link);
break;
case 6:
case 7:
watchdog(EDI_CLASSIFIED_MODULE_NAME, $message, NULL, $severity, $link);
break;
}
}
function _edi_safe_date_fmt($date) {
return $date == 0 ? "_the beginning of time_" : format_date($date);
}
/**
* Determine whether a node is expired given a target timestamp
* An ad is considered to have 'expired' if the $time parameter
* is larger than the node's expires_on field.
*/
function ed_classified_ad_expired($node, $time) {
if ($node->type != EDI_CLASSIFIED_MODULE_NAME) {
return FALSE;
}
return $time >= $node->expires_on;
}
/**
* Helper gets content display name
*/
function _ed_classified_displayname() {
switch (reset(explode('.', DRUPAL_VERSION))) {
case 5:
case 6:
$name = node_get_types('name', 'ed_classified');
break;
case 7:
$name = node_type_get_name('ed_classified');
break;
}
if (isset($name)) {
return $name;
}
else {
return 'undefined';
}
}
function _ed_classified_displayname_parms() {
$name = _ed_classified_displayname();
$parms = array(
'@name' => $name,
'!name' => $name,
'%name' => $name,
);
return $parms;
}
/**
* Make a node edit link
*/
function _ed_classified_make_edit_link($node, $text, $attributes = array()) {
return l($text, "node/{$node->nid}/edit", array(
'attributes' => $attributes,
));
}
/**
* Get duration in days for taxonomy term (array of tids, indexed by vid);
* Expecting array of size 1, so any more is ignored
* if nothing set, use the default value
* TODO - if a single value, not an array, then assume the vid to be the
* Classified Ads vid
*/
function _ed_classified_get_duration($term) {
$duration = 0;
reset($term);
list($vid, $tid) = each($term);
$def = _ed_classified_variable_get('default_ad_duration', EDI_CLASSIFIED_VAR_DEF_EXPIRATION_DAYS);
$name = 'vid_' . $vid . '_tid_' . $tid . '_duration';
$duration = _ed_classified_variable_get($name, $def);
return $duration;
}
// generic debug function
/**
function _dbg($thing, $heading=NULL) {
drupal_set_message("<strong>$heading</strong><pre>".htmlspecialchars(print_r($thing, true)).'</pre>');
}
*/
Functions
Name | Description |
---|---|
ed_classified_ad_expired | Determine whether a node is expired given a target timestamp An ad is considered to have 'expired' if the $time parameter is larger than the node's expires_on field. |
ed_classified_get_adcount | |
ed_classified_get_adcount_for_time_range | Get ad count for time range |
ed_classified_get_ad_expiration | Get the expiration date of a classified ad node |
ed_classified_get_ad_stats | Get stats |
ed_classified_get_latest_ads_list | Get a list of latest ads for block use |
ed_classified_get_popular_ads_list | Get a list of popular ads for block use |
_edi_l | front end to l() due to differences between D5 & D6 causes pain Take D6 params but down convert to D5 if need be |
_edi_safe_date_fmt | |
_edi_wd | shortcut - log something to the watchdog log |
_ed_classified_ad_expired_already | return true if ad has expired |
_ed_classified_ad_expires_soon | Helper function: does $expiration date expire "soon" (soon depends on who you ask) |
_ed_classified_cfg_varname | config variable helpers |
_ed_classified_check_settings | do the sanity-check dance. |
_ed_classified_days_to_seconds | convert days to # seconds |
_ed_classified_displayname | Helper gets content display name |
_ed_classified_displayname_parms | |
_ed_classified_expire_ads | expire old ads |
_ed_classified_get_aged_ads | Get a query result with any ads that have expired prior to a given date, and having a specific publish status |
_ed_classified_get_default_ad_duration_in_seconds | Get default ad duration in seconds |
_ed_classified_get_duration | Get duration in days for taxonomy term (array of tids, indexed by vid); Expecting array of size 1, so any more is ignored if nothing set, use the default value TODO - if a single value, not an array, then assume the vid to be the Classified Ads vid |
_ed_classified_get_ending_date_string | Get just the raw text describing expiration date |
_ed_classified_get_longest_duration | Find the longest duration, in days, for a given set of terms |
_ed_classified_get_primary_category | Helper function to determine the single ad category name to which this node belongs. |
_ed_classified_get_vid | Returns (and possibly creates) a primary vocabulary for classified Repairs association with primary vocabulary if $detect is TRUE. |
_ed_classified_make_category_path | Make a 'path' to a category view for a given tid. |
_ed_classified_make_edit_link | Make a node edit link |
_ed_classified_module_exists | Determine, in a version-friendly way, if a module exists. some folks have decided to change module_exist() to module_exists() for 4.8/5.0. see: http://drupal.org/node/79601 |
_ed_classified_node_is_classified | Is a node really a classified ad? |
_ed_classified_query_results_to_array | Convert db_query results to an array |
_ed_classified_settings_get_banner | Get settings 'banner' |
_ed_classified_variable_get | |
_ed_classified_variable_set | |
_ed_tid_is_classified_term | Is a tid a 'classified' term? Is a tid a child of our taxonomy? |