objectType = $objectType;
$this->object = $this->factory();
//if we didnt get a table, get it from the object class
if ($table === null)
{
$this->table = $object->tableName;
$fields = $this->object->getDbFields(array("id"));
$this->english = $this->object->english;
}
else
$this->table = $table;
//set our numrows.
$this->numRows = $numRows;
}
/**
* create a new object of the type we need.
*
* @param $data optional data to pass to the object.
* @return the newly created object.
*/
function factory($data = null)
{
return new $this->objectType($data);
}
/**
* get our option xml string for what we can sort on.
*
* @return the xml string of sort options
*/
function getSortOptionXml()
{
$rval = "";
foreach ($this->object->getDbFields() AS $key => $value)
{
$rval .= "\t\t\t\n";
}
return $rval;
}
/**
* delete a set of objects.
*
* @param $rs an array of objects to delete.
*/
public function delete($rs)
{
if (count($rs))
foreach ($rs AS $ob)
$ob->delete();
}
/**
* get our pages... default + php, rss, json, and search.
*
* @return the xml string of pages.
*/
function getPagesXml()
{
//obviously we want the base xml.
$xml = parent::getPagesXml();
//main pages are rss and search.
$xml .= $this->getPHPPageXml();
$xml .= $this->getRssPageXml();
$xml .= $this->getJSONPageXml();
$xml .= $this->getSearchPageXml();
return $xml;
}
/**
* our search page xml configuration.
*
* @return the xml string of search page & params.
*/
function getSearchPageXml()
{
$xml = "\tenglish}s from the manager.\">\n";
$xml .= $this->getSearchParamXml();
$xml .= "\t\n";
return $xml;
}
/**
* our search page parameter xml configuration.
*
* @return the xml string of search params.
*/
function getSearchParamXml()
{
$xml = "\t\t\n";
$xml .= "\t\t\n";
$xml .= "\t\t\n";
$xml .= $this->getSortOptionXml();
$xml .= "\t\t\t\n";
$xml .= "\t\t\n";
$xml .= "\t\t\n";
$xml .= "\t\t\t\n";
$xml .= "\t\t\t\n";
$xml .= "\t\t\n";
//any field specific stuff...
$fields = $this->object->getDbFields();
//allow to search for things with this parent.
if ($fields['parent_id'])
$xml .= "\t\t\n";
//or search on a user.
if ($fields['user_id'])
$xml .= "\t\tenglish}\" is_searchable=\"true\"/>\n";
//what if its associated with content?
if ($fields['content_id'])
$xml .= "\t\t\n";
//do we give them lat/lon access?
if ($this->object->useLatLng)
{
if ($fields['lat'])
{
$xml .= "\t\t\n";
$xml .= "\t\t\n";
}
if ($fields['lon'])
{
$xml .= "\t\t\n";
$xml .= "\t\t\n";
}
}
//add date is good.
if ($fields['add_date'])
{
$xml .= "\t\tenglish}'s added on or after it\" regex=\"/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}([0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2})?$/\"/>\n";
$xml .= "\t\tenglish}s added on or before it. used with start date you can specify a range.\" regex=\"/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}([0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2})?$/\"/>\n";
}
//as is edit date
if ($fields['edit_date'])
{
$xml .= "\t\tenglish}'s edited on or after it.\" regex=\"/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}([0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2})?$/\"/>\n";
$xml .= "\t\tenglish} edited on or before it. used with start date you can specify a range\" regex=\"/^[0-9]{4}-[0-9]{1,2}-[0-9]{1,2}([0-9]{1,2}:[0-9]{1,2}:[0-9]{1,2})?$/\"/>\n";
}
return $xml;
}
/**
* our rss page xml configuration.
*
* @return the xml string of rss page & params.
*/
function getRssPageXml()
{
//get our stuff as rss.
$xml = "\t\n";
$xml .= $this->getRssParamXml();
$xml .= "\t\n";
return $xml;
}
/**
* our rss page parameter xml. uses same parameters as search. TODO: add output parameter to search??
*
* @return the xml string of rss params.
*/
function getRssParamXml()
{
//okay, this is a bit of a hack... rss is mostly just search. we might want to add an output to the search page as rss, but fuck it.
return $this->getSearchParamXml();
}
/**
* our json page xml configuration.
*
* @return the xml string of json page & params.
*/
function getJSONPageXml()
{
//get our stuff as rss.
$xml = "\t\n";
$xml .= $this->getJSONParamXml();
$xml .= "\t\n";
return $xml;
}
/**
* our json page parameter xml. uses same parameters as search. TODO: add output parameter to search??
*
* @return the xml string of json params.
*/
function getJSONParamXml()
{
//okay, this is a bit of a hack... json is mostly just search. we might want to add an output to the search page as json, but fuck it.
return $this->getSearchParamXml();
}
/**
* our php page xml configuration.
*
* @return the xml string of php page & params.
*/
function getPHPPageXml()
{
//get our stuff as rss.
$xml = "\t\n";
$xml .= $this->getPHPParamXml();
$xml .= "\t\n";
return $xml;
}
/**
* our php page parameter xml. uses same parameters as search. TODO: add output parameter to search??
*
* @return the xml string of php params.
*/
function getPHPParamXml()
{
//okay, this is a bit of a hack... json is mostly just search. we might want to add an output to the search page as json, but fuck it.
return $this->getSearchParamXml();
}
/**
* initialize our main page... basically redirect to search page. you'll lose your parameters... dont link to main page.
*/
function initMainPage()
{
utilRedirect($this->getUrl(".search"));
}
/**
* draw our main page. TODO: make this a placeholder.
*/
function drawMainPage()
{
echo '
Error. You should be on the search page. Or define ' . get_class($this) . '::drawMainPage()
';
}
/**
* initialize our search page. pass off to initSearch()
*/
function initSearchPage()
{
if((int)$this->params('num_results') > 30)
$this->setParam('num_results', 30);
$this->initSearch($this->params());
}
/**
* initialize our search. sets up the query string.
*
* @param $params a keyed array of parameters. same as search page.
*/
function initSearch($params)
{
//save our parameters.
$this->searchParams = $params;
//did we have a parameter for number of results.
if ($params['num_results'])
$this->numRows = (int)$params['num_results'];
//finally set the query.
$this->query = $this->getSearchQuery($params);
}
/**
* get teh entire search query.
*
* @param $params a keyed array of parameters. same as search page
*
* @return the entire search wuere, limit and all
*/
function getSearchQuery($params)
{
//our basic search
$select = $this->getSearchSelect($params);
$from = $this->getSearchFrom($params);
$where = $this->getSearchWhere($params);
$group = $this->getSearchGroupBy($params);
$order = $this->getSearchOrder($params);
//find out how many results we got.
$countAr = dbFetchAssoc(dbQuery('SELECT count(distinct(o.id)) AS count ' . $from . $where));
$this->numResults = $countAr['count'];
//get our limit stuff...
$this->resultPage = abs((int)$params['result_page']);
//do a bit of error checking on the bounds of the result.
if ($this->resultPage * $this->numRows > $this->numResults)
$this->addError('We do not have that many ' . $this->english . "s.");
//add our limit in here...
$limit = " LIMIT " . $this->resultPage * $this->numRows . ", $this->numRows";
//give it back to the man.
return $select . $from . $where . $group . $order . $limit;
}
/**
* get the select part of our search query.
*
* @param $params a keyed array of parameters. same as search page.
*/
function getSearchSelect($params = array())
{
return "SELECT o.*\n";
}
/**
* get the from/join part of our search query.
*
* @param $params a keyed array of parameters. same as search page.
*/
function getSearchFrom($params = array())
{
$from = "FROM {$this->object->tableName} o \n";
return $from;
}
/**
* get the where part of our search query.
*
* @param $params a keyed array of parameters. same as search page.
*/
function getSearchWhere($params = array())
{
global $me;
$where = "WHERE 1 ";
//our xml configuration.
$xml = $this->parseModuleXml();
$rs = $xml->xpath("//page[@name='search']");
//get our where stuff...
if (is_object($rs[0]->param[0]))
{
//loop thru all our params in our object.
foreach ($rs[0]->param AS $param)
{
//get that param.
$pName = (string)$param['name'];
$pVal = $params[$pName];
//did we get one?
if ($pVal)
{
//by user id.
if ($pName == 'user_id')
$where .= " AND o.user_id = '$pVal' ";
//or content id.
else if ($pName == 'content_id')
$where .= " AND o.content_id = '$pVal' ";
//heres our date stuff...
else if ($pName == 'add_date_start')
$where .= " AND o.add_date >= '$pVal' ";
else if ($pName == 'add_date_stop')
$where .= " AND o.add_date <= '$pVal' ";
else if ($pName == 'edit_date_start')
$where .= " AND o.edit_date >= '$pVal' ";
else if ($pName == 'edit_date_stop')
$where .= " AND o.edit_date <= '$pVal' ";
//how about location?
else if ($pName == 'northlat')
$where .= " AND o.lat <= '$pVal' AND o.lat != 0";
else if ($pName == 'southlat')
$where .= " AND o.lat >= '$pVal'";
else if ($pName == 'eastlon')
$where .= " AND o.lon <= '$pVal' AND o.lon != 0";
else if ($pName == 'westlon')
$where .= " AND o.lon >= '$pVal'";
//if it was passed and is searchable... try it.
else if ($pVal && (string)$param['is_searchable'] == 'true')
$where .= " AND o.$pName = '$pVal'";
}
}
}
//add our privacy where.
$where .= $this->getPrivacyWhere($params);
return $where;
}
/**
* get the group by part of our search query.
*
* @param $params a keyed array of parameters. same as search page.
*/
function getSearchGroupBy($params = array())
{
return '';
}
/**
* get the where by part of our search query. this is specifically for privacy options.
*
* @param $params a keyed array of parameters. same as search page.
*/
function getPrivacyWhere($params = array())
{
}
/**
* get the order part of our search query.
*
* @param $params a keyed array of parameters. same as search page.
*/
function getSearchOrder($params = array())
{
//get our sort...
$sortVar = $params['sort'];
$order = $params['order'];
//if we dont have order and sort... add date desc!
if (!$order && !$sortVar)
$order = 'DESC';
if ($sortVar == 'random')
$sort = " ORDER BY rand() ";
else if ($sortVar)
$sort = " ORDER BY o.$sortVar $order";
else if ($this->object->hasField('add_date'))
$sort = " ORDER BY o.add_date $order";
else
$sort = '';
return $sort;
}
/**
* draws our pagination info wrapped in a div with id of 'pagination'
*/
function drawPagination()
{
echo "
\n";
}
/**
* get a string about our pagination. a-b of x, etc.
*
* @return the string ready to use
*/
function getPaginationStats()
{
return "Showing $this->startRow - $this->endRow of $this->numResults {$this->english}s. ";
}
/**
* get our pagination nav. pages, prev/next, etc.
*
* @return our string ready to use.
*/
function getPaginationNav()
{
$s = '';
//do we have any pages to show?
if ($this->hasPage($this->resultPage-1) || $this->hasPage($this->resultPage+1))
{
$s = "Page: ";
//get our previous
if ($this->resultPage >= 1)
$s .= $this->getPaginationPrev();
//show the nearest 5 pages.
for ($i = $this->resultPage - 5; $i <= $this->resultPage + 5; $i++)
{
if ($i == $this->resultPage)
$s .= " " . ($this->resultPage + 1) . " ";
else if ($this->hasPage($i))
$s .= " " . $this->getPaginationLink($i) . " ";
}
//show our next link
if ($this->endRow < $this->numResults)
$s .= $this->getPaginationNext();
}
return $s;
}
/**
* get a pagination url
*
* @param $page the page to use
*
* @return the url of that page
*/
function getPaginationUrl($page)
{
//update our parameters
$params = $this->searchParams;
$params['page'] = 'search';
$params['result_page'] = $page;
//get the link.
return $this->getUrl($params);
}
/**
* get a pagination link
*
* @param $page the page to link to.
* @param $link the text to link. default null = number of the page.
*
* @return a html link.
*/
function getPaginationLink($page, $link = null)
{
$url = $this->getPaginationUrl($page);
//link to our page if none.
if ($link === null)
$link = $page + 1;
//get our link
return "$link";
}
/**
* get our previous page link.
*
* @return the markup string.
*/
function getPaginationPrev()
{
return $this->getPaginationLink($this->resultPage - 1, '<< prev');
}
/**
* get our next page link.
*
* @return the markup string.
*/
function getPaginationNext()
{
return $this->getPaginationLink($this->resultPage + 1, 'next >>');
}
/**
* determines if a page exists or not
*
* @param $page the number of the page.
*
* @return boolean of its status
*/
function hasPage($page)
{
//negative pages == barf
if ($page < 0)
return false;
//if we show are page, are there still results?
return (($this->numResults - ($page * $this->numRows)) > 0);
}
/**
* calculate our pagination stuff... what we start on, end on, etc.
*/
function calculatePagination()
{
$this->startRow = ($this->resultPage * $this->numRows) + 1;
$this->endRow = ($this->resultPage + 1) * $this->numRows;
if ($this->endRow > $this->numResults)
$this->endRow = $this->numResults;
if ($this->endRow == 0)
$this->startRow = 0;
}
/**
* draw our search page!
*/
function drawSearchPage()
{
$rs = $this->getSearchResult();
if (count($rs))
$this->drawResults($rs);
else
$this->drawNoResults();
}
/**
* get our search result. used to do query, setup array of objects, preload
* secondary objects to save queries (users, comments, etc..), also
* calculates pagination.
*
* @return the array of result objects
*/
function getSearchResult()
{
$ret = array();
$rs = dbQuery($this->query);
while ($ar = dbFetchAssoc($rs))
$ret[] = $this->factory($ar);
if (count($ret))
{
if ($this->object->hasField('user_id'))
{
$users = array();
$user = new User();
foreach ($ret AS $ar)
$users[] = $ar->user_id;
$rs = dbQuery("
SELECT *
FROM {$user->tableName}
WHERE id IN (" . implode(',', array_unique($users)) . ")
");
while ($ar = dbFetchAssoc($rs))
$user = new User($ar);
}
if ($this->object->commentsEnabled)
{
foreach ($ret AS $ar)
$ids[] = $ar->id;
$counts = $this->object->comments->getCommentCount($ids);
foreach ($ret AS $key => $ar)
$ret[$key]->comments->count = (int)$counts[$ar->id];
}
}
//set our pagination
$this->calculatePagination();
return $ret;
}
/**
* draws our result set. pagination, rows, rss link.
*
* @param $rs an array of objects.
*/
function drawResults($rs)
{
$this->drawPagination();
$this->drawRows($rs);
if ($this->useRss)
$this->drawRssLink();
}
/**
* draw our rss link.
*
* @param $params parameters to append to the rss link.
*/
function drawRssLink($params = null)
{
$link = ".rss";
//get some params
if ($params === null)
$params = $this->params();
//add them in.
$get = array();
foreach ($params AS $key => $param)
{
if ($key != 'result_page')
$get[] = "$key=$param";
}
if (count($get))
$link .= "?" . implode("&", $get);
echo $this->getRssLink($link, "Subscribe to this {$this->object->english} feed.");
}
/**
* this function is called on a search page when there are no results.
*/
function drawNoResults()
{
echo "
No {$this->english}s found.
\n";
}
/**
* this draws the rows for each object. calls drawHeaderRow() on teh object,
* and then drawRow() on each object in teh result set. each object is
* wrapped in a div of class $class.
*
* @param $rs an array of objects to draw.
* @param $class the css class to wrap the objects in.
*/
function drawRows($rs, $class = null)
{
if ($class === null)
$class = "contentRow " . strtolower($this->objectType);
if (count($rs))
{
$this->object->drawHeaderRow();
foreach ($rs AS $ar)
{
$this->object = $ar;
if ($this->object->canView())
{
echo "\n
\n";
$this->object->drawRow();
echo "
\n";
}
}
}
}
/**
* This draws all the objects in one-line form. they are wrapped in a div of objectType + Line
*
* @param $rs an array of objects to draw.
* @param $class the css class to wrap the objects in.
*/
function drawLines($rs, $class = null)
{
if ($class === null)
$class = strtolower($this->objectType) . "Line";
if (count($rs))
{
$this->object->drawHeaderLine();
foreach ($rs AS $ar)
{
$this->object = $ar;
if ($this->object->canView())
{
echo "\n
\n";
$this->object->drawLine();
echo "
\n";
}
}
}
}
/**
* search for a user's content..
*
* @param $userId the id of the user.
* @param $limit max results to get.
*
* @return the result set.
*/
function userSearch($userId, $limit = null)
{
return $this->search(array(
'user_id' => $userId
), $limit);
}
/**
* search for objects. you can call this to do custom searches.
*
* @param $params a keyed array of parameters to search on.
* @param $limit the maximum results to return. defaults to numRows, pass -1 for unlimited.
*
* @return the result set.
*/
public function search($params, $limit = null)
{
//know your limit!
if ($limit == -1)
$limit = 99999999;
//set it!
if ($limit !== null)
$params['num_results'] = $limit;
//prep it!
$this->initSearch($params);
//now actually search
return $this->getSearchResult();
}
/**
* initialize our rss page... no header/footer.
*/
function initRssPage()
{
$this->needHeader = false;
$this->needFooter = false;
if((int)$this->params('num_results') > 30)
$this->setParam('num_results', 30);
}
/**
* draw our rss page. generate, draw, and save.
*/
function drawRssPage()
{
$feed = $this->generateRss($this->params());
$feed->saveFeed('RSS2.0', '', true);
}
/**
* generate our rss. uses the feedcreator class.
*
* @param $params a keyed array of parameters as for search used to search for rss items.
* @param $useCached boolean of whether we want to cache. default: true
*
* @return the UniversialFeedCreator object.
*/
function generateRss($params = array(), $useCached = true)
{
require_once("lib/feedcreator.class.php");
//create the object
$rss = new UniversalFeedCreator();
//do we use cached?
if ($useCached)
$rss->useCached(); // use cached version if age<1 hour
$rss->title = SITE_NAME . " " . $this->object->english . " feed";
$rss->description = $this->object->english . " feed";
$item->descriptionHtmlSyndicated = true;
//get our links...
$rss->link = "http://" . SITE_HOSTNAME;
$rss->syndicationURL = "http://" . SITE_HOSTNAME . $_SERVER["PHP_SELF"];
//do our search
$rs = $this->search($params);
if (count($rs))
{
foreach ($rs AS $ob)
{
$item = $ob->getRssItem();
$rss->addItem($item);
}
}
return $rss;
}
/**
* initialize our json page... no header/footer, we need the json library.
*/
function initJSONPage()
{
require_once("lib/json.inc.php");
$this->needHeader = false;
$this->needFooter = false;
if((int)$this->params('num_results') > 30)
$this->setParam('num_results', 30);
}
/**
* draw our json page. get public data and encode.
*/
function drawJSONPage()
{
$data = $this->getPublicData($this->params());
echo json_encode($data);
}
/**
* intialize our php serialize() page. no header/footer
*/
function initPHPPage()
{
$this->needHeader = false;
$this->needFooter = false;
if((int)$this->params('num_results') > 30)
$this->setParam('num_results', 30);
}
/**
* draw our php serialize page... echo the serialized() public data.
*/
function drawPHPPage()
{
echo serialize($this->getPublicData($this->params()));
}
/**
* get our public data. actually its an array of the object's public data... but same diff.
*
* @param $params a keyed array of parameters to search on. same as search()
*
* @return an array of public data. woot!
*/
function getPublicData($params)
{
$data = array();
$rs = $this->search($params);
if (count($rs))
foreach ($rs AS $ob)
$data[] = $ob->getPublicData();
return $data;
}
/**
* draws the users content...
*
* @param $userId the id of the user (hmm.. ;)
* @param $count number of results to print. default: 4
*/
function drawUserContent($userId, $count = 4)
{
$user = new User($userId);
//do our search
$rs = $this->userSearch($userId, $count);
//what did we get?
if (count($rs))
{
//dra our header and pagination
echo "
";
//our content
$this->drawRows($rs);
//finally rss
echo $this->getRssLink(".rss?user_id=$userId", "Subscribe to " . $user->getName() . "'s " . ucfirst(utilPluralize($this->object->english, count($rs))) . " feed.");
}
}
/**
* This function determines admin status. (passes off to object->isAdmin())
* @return true if they are admin, false if not.
*/
public function isAdmin()
{
return (bool)$this->object->isAdmin();
}
}