| 1 |
<?php |
| 2 |
#TODO: implement search filter (e.g. 'contains the words', for microblogs) |
| 3 |
#TODO: implement weighting, so that high-volume feeds (libre.fm, delicious) don't |
| 4 |
# drown out important things like blog posts and videos |
| 5 |
#TODO: store table names as variables |
| 6 |
#TODO: XSLT output (can this handle inheritance? A little formatting still needed, I think) |
| 7 |
#TODO: multiple links -- combine timeSince if they're all the same... |
| 8 |
#TODO: it'd be cool to combine Delicious, Google Reader and StumbleUpon stories... |
| 9 |
# and Facebook Posted Items... because sometimes that happens for the same link |
| 10 |
#TODO: need to query for more if not enough retrieved (LIMIT estimated) |
| 11 |
|
| 12 |
//function __autoload($class_name){ |
| 13 |
// require_once 'modules/' . strtolower($class_name) . '.class.php'; |
| 14 |
//} |
| 15 |
require('entry.class.php'); |
| 16 |
require('settings.php'); |
| 17 |
require('modules.php'); |
| 18 |
|
| 19 |
define('ABS_PATH', dirname(__FILE__)); |
| 20 |
define('DEFAULT_ENTRY_ICON', '/default_icon.png'); |
| 21 |
|
| 22 |
/** |
| 23 |
* Load db settings and connect. |
| 24 |
* @return database handling |
| 25 |
*/ |
| 26 |
function db_connect() { |
| 27 |
$dbh = @mysql_connect(DB_HOST, DB_USER, DB_PASS); |
| 28 |
if(!$dbh) |
| 29 |
die('Could not connect: ' . mysql_error()); |
| 30 |
if(!mysql_select_db(DB_NAME, $dbh)) |
| 31 |
die('Could not select database: ' . mysql_error()); |
| 32 |
|
| 33 |
return $dbh; |
| 34 |
} |
| 35 |
|
| 36 |
/** |
| 37 |
* Load entries from the database, return as array. |
| 38 |
* @param $dbh -- database link identifier |
| 39 |
* @param $filter_query -- WHERE clauses, if any |
| 40 |
* @param $max -- number of desired entries to load. |
| 41 |
* @param $more -- used as a pager so that, if this function is called multiple |
| 42 |
* times with other parameters constant but $more increment, it |
| 43 |
* will return the next entries from the same query... |
| 44 |
*/ |
| 45 |
function load_entries($dbh, $filter_query, $limit, $more = 0) { |
| 46 |
$limit = (int)($limit); |
| 47 |
$entries = array(); |
| 48 |
|
| 49 |
// Load entries |
| 50 |
$sql = "SELECT e.*, f.type as feed_type, f.title as feed_title, f.link as feed_link, f.id as feed_id FROM entries e |
| 51 |
LEFT OUTER JOIN feeds f ON f.id=e.feed_id |
| 52 |
$filter_query |
| 53 |
ORDER BY e.rec_updated DESC |
| 54 |
LIMIT ".$more*$limit .', '. $limit; |
| 55 |
|
| 56 |
$result = mysql_query($sql, $dbh); |
| 57 |
if(!$result) |
| 58 |
die('Query failed: ' . mysql_error($dbh)); |
| 59 |
|
| 60 |
while ($row = mysql_fetch_assoc($result)) { |
| 61 |
$class = class_exists($row['feed_type']) ? $row['feed_type'] : 'Entry'; |
| 62 |
$entries[] = new $class($row); |
| 63 |
} |
| 64 |
|
| 65 |
// TODO: look for a more elegant way to express this |
| 66 |
|
| 67 |
// Join any duplicate entries |
| 68 |
for($i = 0; $i < count($entries); $i++){ |
| 69 |
while(is_callable(array($entries[$i], 'equals')) and |
| 70 |
$i+1 < count($entries) and |
| 71 |
is_callable(array($entries[$i+1], 'equals')) and |
| 72 |
$entries[$i]->equals($entries[$i+1])){ |
| 73 |
|
| 74 |
$entries[$i]->merge($entries[$i+1]); |
| 75 |
if($i+2 < count($entries)) |
| 76 |
$entries = array_merge( |
| 77 |
array_slice($entries, 0, $i+1), |
| 78 |
array_slice($entries, $i+2)); |
| 79 |
else |
| 80 |
$entries = array_slice($entries, 0, $i+1); |
| 81 |
} |
| 82 |
} |
| 83 |
|
| 84 |
return $entries; |
| 85 |
} |
| 86 |
|
| 87 |
/** |
| 88 |
* Return an unordered list of the entries from the database |
| 89 |
* which match the following criteria. |
| 90 |
*/ |
| 91 |
function get_entries($filters = array(), $max = 20, $with_like = array()) { |
| 92 |
$dbh = db_connect(); |
| 93 |
|
| 94 |
// Build query filters |
| 95 |
$filter_query = ""; |
| 96 |
if ($filters) { |
| 97 |
$fields = array('tag' => 't.name', 'feed' => 'f.id'); |
| 98 |
|
| 99 |
// Load filters |
| 100 |
foreach ($filters as $key => $value) { |
| 101 |
if ($value) { |
| 102 |
$key = $fields[$key]; |
| 103 |
|
| 104 |
// If string, add check for this single value |
| 105 |
if (!is_array($value)) { |
| 106 |
$value = mysql_real_escape_string($value); |
| 107 |
$this_filter_query = "$key='$value'"; |
| 108 |
} |
| 109 |
|
| 110 |
// If array, match any of the values |
| 111 |
else { |
| 112 |
$this_filter_query = ''; |
| 113 |
foreach ($value as $this_value) { |
| 114 |
$this_value = mysql_real_escape_string($this_value); |
| 115 |
$this_filter_query .= ($this_filter_query ? ' OR ' : '') ."$key='$this_value'"; |
| 116 |
} |
| 117 |
} |
| 118 |
$filter_query .= (!$filter_query ? ' WHERE ' : ' AND ') ."($this_filter_query)"; |
| 119 |
} |
| 120 |
|
| 121 |
if ($with_like) { |
| 122 |
$filter_query .= " OR e.title LIKE '%$with_like%' "; |
| 123 |
} |
| 124 |
// If filtering by tag, join tag tables |
| 125 |
if (isset($filters['tag']) && $filters['tag']) { |
| 126 |
$filter_query = 'LEFT OUTER JOIN tag_relationships x ON e.id=x.entry_id |
| 127 |
LEFT OUTER JOIN tags t ON x.tag_id=t.id '. $filter_query; |
| 128 |
} |
| 129 |
} |
| 130 |
} |
| 131 |
|
| 132 |
|
| 133 |
$entries = load_entries($dbh, $filter_query, $max*2); |
| 134 |
if (!$entries) { |
| 135 |
return '<p>No activity.</p>'; //nothing to show |
| 136 |
} |
| 137 |
$more = 0; //used later if we need to load more |
| 138 |
|
| 139 |
$ul = "\n<ul>"; |
| 140 |
|
| 141 |
// Add entries to list |
| 142 |
for($i = 0; $i < count($entries); $i++){ |
| 143 |
// Get more entries if we're on the last one |
| 144 |
if ($i == count($entries)-1) { |
| 145 |
$more++; |
| 146 |
$entries = array_merge($entries, load_entries($dbh, $filter_query, $max*2, $more)); |
| 147 |
} |
| 148 |
|
| 149 |
|
| 150 |
|
| 151 |
$entry = $entries[$i]; |
| 152 |
|
| 153 |
// Check for a series of events |
| 154 |
$multiple = array(); |
| 155 |
if($entry->canHaveMultiples()) { |
| 156 |
while($i+1 < count($entries) && $entry->groupTogether($entries[$i+1])){ |
| 157 |
$multiple[] = $entries[$i+1]; |
| 158 |
|
| 159 |
$i++; |
| 160 |
|
| 161 |
// Get more entries if we're on the last one TODO: this will never stop if whole query is multiples |
| 162 |
if ($i == count($entries)-1) { |
| 163 |
$more++; |
| 164 |
$entries = array_merge($entries, load_entries($dbh, $filter_query, $max*2, $more)); |
| 165 |
} |
| 166 |
} |
| 167 |
} |
| 168 |
if(empty($multiple)) |
| 169 |
$item = $entry->single(); |
| 170 |
else |
| 171 |
if (!$filter_query) |
| 172 |
$item = $entry->multiple( $multiple ); |
| 173 |
else |
| 174 |
$item = $entry->multiple( $multiple, 10 ); |
| 175 |
|
| 176 |
// Bail if entry display returned false |
| 177 |
if (!$item) { |
| 178 |
continue; |
| 179 |
} |
| 180 |
$ul .= "\n\t<li class='$entry->feed_type feed$entry->feed_id'>$item</li>"; |
| 181 |
|
| 182 |
#TODO: this is temporary |
| 183 |
if(!isset($count)) $count = 0; |
| 184 |
$count++; |
| 185 |
if($count > $max) |
| 186 |
break; |
| 187 |
} |
| 188 |
$ul .= "\n</ul>"; |
| 189 |
return $ul; |
| 190 |
} |