/** * Create a new publication type * * @param $args['name'] name of the publication type * @param $args['descr'] description of the publication type * @param $args['config'] configuration of the publication type * @return int publication type ID on success, false on failure */ function publications_adminapi_createpubtype($args) { // Get arguments from argument array extract($args); // Argument check - make sure that all required arguments are present // and in the right format, if not then set an appropriate error // message and return // Note : since we have several arguments we want to check here, we'll // report all those that are invalid at the same time... $invalid = array(); if (!isset($name) || !is_string($name) || empty($name)) { $invalid[] = 'name'; } if (!isset($config) || !is_array($config) || count($config) == 0) { $invalid[] = 'configuration'; } if (count($invalid) > 0) { $msg = xarML('Invalid #(1) for #(2) function #(3)() in module #(4)', join(', ', $invalid), 'admin', 'createpubtype', 'Publications'); throw new BadParameterException(null, $msg); } if (empty($descr)) { $descr = $name; } // Publication type names *must* be lower-case for now $name = strtolower($name); // Security check - we require ADMIN rights here if (!xarSecurityCheck('AdminPublications')) { return; } if (!xarModAPILoad('publications', 'user')) { return; } // Make sure we have all the configuration fields we need $pubfields = xarModAPIFunc('publications', 'user', 'getpubfields'); foreach ($pubfields as $field => $value) { if (!isset($config[$field])) { $config[$field] = ''; } } // Get database setup $dbconn = xarDB::getConn(); $xartable = xarDB::getTables(); $pubtypestable = $xartable['publication_types']; // Get next ID in table $nextId = $dbconn->GenId($pubtypestable); // Insert the publication type $query = "INSERT INTO {$pubtypestable} (pubtype_id, pubtypename,\n pubtypedescr, pubtypeconfig)\n VALUES (?,?,?,?)"; $bindvars = array($nextId, $name, $descr, serialize($config)); $result =& $dbconn->Execute($query, $bindvars); if (!$result) { return; } // Get ptid to return $ptid = $dbconn->PO_Insert_ID($pubtypestable, 'pubtype_id'); // Don't call creation hooks here... //xarModCallHooks('item', 'create', $ptid, 'ptid'); return $ptid; }
/** * Delete a publication type * * @param $args['ptid'] ID of the publication type * @return bool true on success, false on failure */ function publications_adminapi_deletepubtype($args) { // Get arguments from argument array extract($args); // Argument check - make sure that all required arguments are present // and in the right format, if not then set an appropriate error // message and return if (!isset($ptid) || !is_numeric($ptid) || $ptid < 1) { $msg = xarML('Invalid #(1) for #(2) function #(3)() in module #(4)', 'publication type ID', 'admin', 'deletepubtype', 'Publications'); throw new BadParameterException(null, $msg); } // Security check - we require ADMIN rights here if (!xarSecurityCheck('AdminPublications', 1, 'Publication', "{$ptid}:All:All:All")) { return; } // Load user API to obtain item information function if (!xarModAPILoad('publications', 'user')) { return; } // Get current publication types $pubtypes = xarModAPIFunc('publications', 'user', 'get_pubtypes'); if (!isset($pubtypes[$ptid])) { $msg = xarML('Invalid #(1) for #(2) function #(3)() in module #(4)', 'publication type ID', 'admin', 'deletepubtype', 'Publications'); throw new BadParameterException(null, $msg); } // Get database setup $dbconn = xarDB::getConn(); $xartable = xarDB::getTables(); $pubtypestable = $xartable['publication_types']; // Delete the publication type $query = "DELETE FROM {$pubtypestable}\n WHERE pubtype_id = ?"; $result =& $dbconn->Execute($query, array($ptid)); if (!$result) { return; } $publicationstable = $xartable['publications']; // Delete all publications for this publication type $query = "DELETE FROM {$publicationstable}\n WHERE pubtype_id = ?"; $result =& $dbconn->Execute($query, array($ptid)); if (!$result) { return; } // TODO: call some kind of itemtype delete hooks here, once we have those //xarModCallHooks('itemtype', 'delete', $ptid, // array('module' => 'publications', // 'itemtype' =>'ptid')); return true; }
/** * redirect to a site based on some URL field of the item */ function publications_user_redirect($args) { // Get parameters from user if (!xarVarFetch('id', 'id', $id, NULL, XARVAR_NOT_REQUIRED)) { return; } // Override if needed from argument array extract($args); if (!isset($id) || !is_numeric($id) || $id < 1) { return xarML('Invalid publication ID'); } // Load API if (!xarModAPILoad('publications', 'user')) { return; } // Get publication $publication = xarModAPIFunc('publications', 'user', 'get', array('id' => $id)); if (!is_array($publication)) { $msg = xarML('Failed to retrieve publication in #(3)_#(1)_#(2).php', 'user', 'get', 'publications'); throw new DataNotFoundException(null, $msg); } $ptid = $publication['pubtype_id']; // Get publication types $pubtypes = xarModAPIFunc('publications', 'user', 'get_pubtypes'); // TODO: improve this e.g. when multiple URL fields are present // Find an URL field based on the pubtype configuration foreach ($pubtypes[$ptid]['config'] as $field => $value) { if (empty($value['label'])) { continue; } if ($value['format'] == 'url' && !empty($publication[$field]) && $publication[$field] != 'http://') { // TODO: add some verifications here ! $hooks = xarModCallHooks('item', 'display', $id, array('module' => 'publications', 'itemtype' => $ptid), 'publications'); xarController::redirect($article[$field]); return true; } elseif ($value['format'] == 'urltitle' && !empty($publication[$field]) && substr($publication[$field], 0, 2) == 'a:') { $array = unserialize($publication[$field]); if (!empty($array['link']) && $array['link'] != 'http://') { $hooks = xarModCallHooks('item', 'display', $id, array('module' => 'publications', 'itemtype' => $ptid), 'publications'); xarController::redirect($array['link']); return true; } } } return xarML('Unable to find valid redirect field'); }
/** * count number of items depending on additional module criteria * * @param $args['catid'] string of category id(s) that we're counting in, or * @param $args['cids'] array of cids that we are counting in (OR/AND) * @param $args['andcids'] true means AND-ing categories listed in cids * * @param $args['owner'] the ID of the author * @param $args['ptid'] publication type ID (for news, sections, reviews, ...) * @param $args['state'] array of requested status(es) for the publications * @param $args['startdate'] publications published at startdate or later * (unix timestamp format) * @param $args['enddate'] publications published before enddate * (unix timestamp format) * @return int number of items */ function publications_userapi_countitems($args) { // Database information $dbconn = xarDB::getConn(); // Get the field names and LEFT JOIN ... ON ... parts from publications // By passing on the $args, we can let leftjoin() create the WHERE for // the publications-specific columns too now $publicationsdef = xarModAPIFunc('publications', 'user', 'leftjoin', $args); // TODO: make sure this is SQL standard // Start building the query if ($dbconn->databaseType == 'sqlite') { $query = 'SELECT COUNT(*) FROM ( SELECT DISTINCT ' . $publicationsdef['field'] . ' FROM ' . $publicationsdef['table']; // WATCH OUT, UNBALANCED } else { $query = 'SELECT COUNT(DISTINCT ' . $publicationsdef['field'] . ')'; $query .= ' FROM ' . $publicationsdef['table']; } if (!isset($args['cids'])) { $args['cids'] = array(); } if (!isset($args['andcids'])) { $args['andcids'] = false; } if (count($args['cids']) > 0 || !empty($args['catid'])) { // Load API if (!xarModAPILoad('categories', 'user')) { return; } // Get the LEFT JOIN ... ON ... and WHERE (!) parts from categories $args['modid'] = xarModGetIDFromName('publications'); if (isset($args['ptid']) && !isset($args['itemtype'])) { $args['itemtype'] = $args['ptid']; } $categoriesdef = xarModAPIFunc('categories', 'user', 'leftjoin', $args); $query .= ' LEFT JOIN ' . $categoriesdef['table']; $query .= ' ON ' . $categoriesdef['field'] . ' = ' . $publicationsdef['id']; $query .= $categoriesdef['more']; $docid = 1; } // Create the WHERE part $where = array(); // we rely on leftjoin() to create the necessary publications clauses now if (!empty($publicationsdef['where'])) { $where[] = $publicationsdef['where']; } if (!empty($docid)) { // we rely on leftjoin() to create the necessary categories clauses $where[] = $categoriesdef['where']; } if (count($where) > 0) { $query .= ' WHERE ' . join(' AND ', $where); } // Balance parentheses if ($dbconn->databaseType == 'sqlite') { $query .= ')'; } // Run the query - finally :-) $result =& $dbconn->Execute($query); if (!$result) { return; } if ($result->EOF) { return; } $num = $result->fields[0]; $result->Close(); return $num; }
/** * get the number of publications per publication type and category * * @param $args['state'] array of requested status(es) for the publications * @param $args['ptid'] publication type ID * @param $args['cids'] array of category IDs (OR/AND) * @param $args['andcids'] true means AND-ing categories listed in cids * @param $args['groupcids'] the number of categories you want items grouped by * @param $args['reverse'] default is ptid => cid, reverse (1) is cid => ptid * @return array array( $ptid => array( $cid => $count) ), * or false on failure */ function publications_userapi_getpubcatcount($args) { /* static $pubcatcount = array(); if (count($pubcatcount) > 0) { return $pubcatcount; } */ $pubcatcount = array(); // Get database setup $dbconn = xarDB::getConn(); // Get the LEFT JOIN ... ON ... and WHERE parts from publications $publicationsdef = xarModAPIFunc('publications', 'user', 'leftjoin', $args); // Load API if (!xarModAPILoad('categories', 'user')) { return; } $args['modid'] = xarMod::getRegID('publications'); if (isset($args['ptid']) && !isset($args['itemtype'])) { $args['itemtype'] = $args['ptid']; } // Get the LEFT JOIN ... ON ... and WHERE parts from categories $categoriesdef = xarModAPIFunc('categories', 'user', 'leftjoin', $args); // Get count $query = 'SELECT ' . $publicationsdef['pubtype_id'] . ', ' . $categoriesdef['category_id'] . ', COUNT(*) FROM ' . $publicationsdef['table'] . ' LEFT JOIN ' . $categoriesdef['table'] . ' ON ' . $categoriesdef['field'] . ' = ' . $publicationsdef['field'] . $categoriesdef['more'] . ' WHERE ' . $categoriesdef['where'] . ' AND ' . $publicationsdef['where'] . ' GROUP BY ' . $publicationsdef['pubtype_id'] . ', ' . $categoriesdef['category_id']; $result =& $dbconn->Execute($query); if (!$result) { return; } if ($result->EOF) { if (!empty($args['ptid']) && empty($args['reverse'])) { $pubcatcount[$args['ptid']] = array(); } return $pubcatcount; } while (!$result->EOF) { // we may have 1 or more cid fields here, depending on what we're // counting (cfr. AND in categories) $fields = $result->fields; $ptid = array_shift($fields); $count = array_pop($fields); // TODO: use multi-level array for multi-category grouping ? $cid = join('+', $fields); if (empty($args['reverse'])) { $pubcatcount[$ptid][$cid] = $count; } else { $pubcatcount[$cid][$ptid] = $count; } $result->MoveNext(); } foreach ($pubcatcount as $id1 => $val) { $total = 0; foreach ($val as $id2 => $count) { $total += $count; } $pubcatcount[$id1]['total'] = $total; } return $pubcatcount; }
/** * search publications (called as hook from search module, or directly with pager) * * @param $args['objectid'] could be the query ? (currently unused) * @param $args['extrainfo'] all other parameters ? (currently unused) * @return array output */ function publications_user_search($args) { // pager stuff if (!xarVarFetch('startnum', 'int:0', $startnum, NULL, XARVAR_NOT_REQUIRED)) { return; } // categories stuff if (!xarVarFetch('cids', 'array', $cids, NULL, XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('andcids', 'str', $andcids, NULL, XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('catid', 'str', $catid, NULL, XARVAR_NOT_REQUIRED)) { return; } // single publication type when called via the pager if (!xarVarFetch('ptid', 'id', $ptid, NULL, XARVAR_NOT_REQUIRED)) { return; } // multiple publication types when called via search hooks if (!xarVarFetch('ptids', 'array', $ptids, NULL, XARVAR_NOT_REQUIRED)) { return; } // date stuff via forms if (!xarVarFetch('publications_startdate', 'str', $startdate, NULL, XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('publications_enddate', 'str', $enddate, NULL, XARVAR_NOT_REQUIRED)) { return; } // date stuff via URLs if (!xarVarFetch('start', 'int:0', $start, NULL, XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('end', 'int:0', $end, NULL, XARVAR_NOT_REQUIRED)) { return; } // search button was pressed if (!xarVarFetch('search', 'str', $search, NULL, XARVAR_NOT_REQUIRED)) { return; } // select by article state (array or string) if (!xarVarFetch('state', 'isset', $state, NULL, XARVAR_NOT_REQUIRED)) { return; } // yes, this is the query if (!xarVarFetch('q', 'str', $q, NULL, XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('author', 'str', $author, NULL, XARVAR_NOT_REQUIRED)) { return; } // filter by category if (!xarVarFetch('by', 'str', $by, NULL, XARVAR_NOT_REQUIRED)) { return; } // can't use list enum here, because we don't know which sorts might be used if (!xarVarFetch('sort', 'regexp:/^[\\w,]*$/', $sort, NULL, XARVAR_NOT_REQUIRED)) { return; } // boolean AND/OR for words (no longer used) //if(!xarVarFetch('bool', 'str', $bool, NULL, XARVAR_NOT_REQUIRED)) {return;} // search in specific fields if (!xarVarFetch('publications_fields', 'isset', $fields, NULL, XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('searchtype', 'isset', $searchtype, NULL, XARVAR_NOT_REQUIRED)) { return; } if (isset($args['objectid'])) { $ishooked = 1; } else { $ishooked = 0; if (empty($fields)) { // search in specific fields via URLs if (!xarVarFetch('fields', 'isset', $fields, NULL, XARVAR_NOT_REQUIRED)) { return; } } } // TODO: could we need this someday ? if (isset($args['extrainfo'])) { extract($args['extrainfo']); } // TODO: clean up this copy & paste stuff :-) // Default parameters if (!isset($startnum)) { $startnum = 1; } if (!isset($numitems)) { $numitems = 20; } if (!xarModAPILoad('publications', 'user')) { return; } // Get publication types $pubtypes = xarModAPIFunc('publications', 'user', 'get_pubtypes'); if (xarSecurityCheck('AdminPublications', 0)) { $isadmin = true; } else { $isadmin = false; } // frontpage or approved state if (!$isadmin || !isset($state)) { $state = array(PUBLICATIONS_STATE_FRONTPAGE, PUBLICATIONS_STATE_APPROVED); } elseif (is_string($state)) { if (strpos($state, ' ')) { $state = explode(' ', $state); } elseif (strpos($state, '+')) { $state = explode('+', $state); } else { $state = array($state); } } $seenstate = array(); foreach ($state as $that) { if (empty($that) || !is_numeric($that)) { continue; } $seenstate[$that] = 1; } $state = array_keys($seenstate); if (count($state) != 2 || !in_array(PUBLICATIONS_STATE_APPROVED, $state) || !in_array(PUBLICATIONS_STATE_FRONTPAGE, $state)) { $stateline = implode('+', $state); } else { $stateline = null; } if (!isset($sort)) { $sort = null; } // default publication type(s) to search in if (!empty($ptid) && isset($pubtypes[$ptid])) { $ptids = array($ptid); $settings = unserialize(xarModVars::get('publications', 'settings.' . $ptid)); if (empty($settings['show_categories'])) { $show_categories = 0; } else { $show_categories = 1; } } elseif (!empty($ptids) && count($ptids) > 0) { foreach ($ptids as $curptid) { // default view doesn't apply here ?! } $show_categories = 1; } elseif (!isset($ptids)) { // $ptids = array(xarModVars::get('publications','defaultpubtype')); $ptids = array(); foreach ($pubtypes as $pubid => $pubtype) { $ptids[] = $pubid; } $show_categories = 1; } else { // TODO: rethink this when we're dealing with multi-pubtype categories $show_categories = 0; } // turn $catid into $cids array (and set $andcids flag) if (!empty($catid)) { if (strpos($catid, ' ')) { $cids = explode(' ', $catid); $andcids = true; } elseif (strpos($catid, '+')) { $cids = explode('+', $catid); $andcids = true; } else { $cids = explode('-', $catid); $andcids = false; } } $seencid = array(); $catid = null; if (isset($cids) && is_array($cids)) { foreach ($cids as $cid) { if (empty($cid) || !preg_match('/^_?[0-9]+$/', $cid)) { continue; } $seencid[$cid] = 1; } $cids = array_keys($seencid); if ($andcids) { $catid = join('+', $cids); } else { $catid = join('-', $cids); } } $seenptid = array(); if (isset($ptids) && is_array($ptids)) { foreach ($ptids as $curptid) { if (empty($curptid) || !isset($pubtypes[$curptid])) { continue; } $seenptid[$curptid] = 1; } $ptids = array_keys($seenptid); } /* Ensure whitespace alone not passed to api -causes errors */ if (isset($q) && trim($q) === '') { $q = null; } // Find the id of the author we're looking for if (!empty($author)) { // Load API if (!xarModAPILoad('roles', 'user')) { return; } $user = xarModAPIFunc('roles', 'user', 'get', array('name' => $author)); if (!empty($user['uid'])) { $owner = $user['uid']; } else { $owner = null; $author = null; } } else { $owner = null; $author = null; } if (isset($start) && is_numeric($start)) { $startdate = xarLocaleFormatDate("%Y-%m-%d %H:%M:%S", $start); } if (isset($end) && is_numeric($end)) { $enddate = xarLocaleFormatDate("%Y-%m-%d %H:%M:%S", $end); } if (empty($fields)) { $fieldlist = array('title', 'description', 'summary', 'body1'); } else { $fieldlist = array_keys($fields); // don't pass fields via URLs if we stick to the default list if (count($fields) == 3 && isset($fields['title']) && isset($fields['description']) && isset($fields['summary']) && isset($fields['body1'])) { $fields = null; } } // Set default searchtype to 'fulltext' if necessary $fulltext = xarModVars::get('publications', 'fulltextsearch'); if (!isset($searchtype) && !empty($fulltext)) { $searchtype = 'fulltext'; } // FIXME: fulltext only supports searching in all configured text fields ! if (empty($fields) && !empty($fulltext) && !empty($searchtype) && $searchtype == 'fulltext') { $fieldlist = explode(',', $fulltext); } $data = array(); $data['results'] = array(); $data['state'] = ''; $data['ishooked'] = $ishooked; // TODO: MichelV: $ishooked is never empty, but either 0 or 1 if (empty($ishooked)) { $data['q'] = isset($q) ? xarVarPrepForDisplay($q) : null; $data['author'] = isset($author) ? xarVarPrepForDisplay($author) : null; $data['searchtype'] = $searchtype; } if ($isadmin) { $states = xarModAPIFunc('publications', 'user', 'getstates'); $data['statelist'] = array(); foreach ($states as $id => $name) { $data['statelist'][] = array('id' => $id, 'name' => $name, 'checked' => in_array($id, $state)); } } // TODO: show field labels when we're dealing with only 1 pubtype $data['fieldlist'] = array(array('id' => 'title', 'name' => xarML('title'), 'checked' => in_array('title', $fieldlist)), array('id' => 'description', 'name' => xarML('description'), 'checked' => in_array('description', $fieldlist)), array('id' => 'summary', 'name' => xarML('summary'), 'checked' => in_array('summary', $fieldlist)), array('id' => 'body1', 'name' => xarML('body1'), 'checked' => in_array('body1', $fieldlist)), array('id' => 'notes', 'name' => xarML('notes'), 'checked' => in_array('notes', $fieldlist))); $data['publications'] = array(); foreach ($pubtypes as $pubid => $pubtype) { if (!empty($seenptid[$pubid])) { $checked = ' checked="checked"'; } else { $checked = ''; } $data['publications'][] = array('id' => $pubid, 'description' => xarVarPrepForDisplay($pubtype['description']), 'checked' => $checked); } $data['categories'] = array(); if (!empty($by) && $by == 'cat') { $catarray = array(); foreach ($ptids as $curptid) { // get root categories for this publication type $catlinks = xarModAPIFunc('categories', 'user', 'getallcatbases', array('module' => 'publications', 'itemtype' => $curptid)); foreach ($catlinks as $cat) { $catarray[$cat['category_id']] = $cat['name']; } } foreach ($catarray as $cid => $title) { $select = xarModAPIFunc('categories', 'visual', 'makeselect', array('cid' => $cid, 'return_itself' => true, 'select_itself' => true, 'values' => &$seencid, 'multiple' => 1)); $data['categories'][] = array('cattitle' => $title, 'catselect' => $select); } $data['searchurl'] = xarModURL('search', 'user', 'main'); } else { $data['searchurl'] = xarModURL('search', 'user', 'main', array('by' => 'cat')); } $now = time(); if (empty($startdate)) { $startdate = null; $data['startdate'] = 'N/A'; } else { if (!preg_match('/[a-zA-Z]+/', $startdate)) { $startdate .= ' GMT'; } $startdate = strtotime($startdate); // adjust for the user's timezone offset $startdate -= xarMLS_userOffset() * 3600; if ($startdate > $now && !$isadmin) { $startdate = $now; } $data['startdate'] = $startdate; } if (empty($enddate)) { $enddate = $now; $data['enddate'] = 'N/A'; } else { if (!preg_match('/[a-zA-Z]+/', $enddate)) { $enddate .= ' GMT'; } $enddate = strtotime($enddate); // adjust for the user's timezone offset $enddate -= xarMLS_userOffset() * 3600; if ($enddate > $now && !$isadmin) { $enddate = $now; } $data['enddate'] = $enddate; } if (!empty($q) || !empty($author) && isset($owner) || !empty($search) || !empty($ptid) || !empty($startdate) || $enddate != $now || !empty($catid)) { $getfields = array('id', 'title', 'start_date', 'pubtype_id', 'cids'); // Return the relevance when using MySQL full-text search //if (!empty($search) && !empty($searchtype) && substr($searchtype,0,8) == 'fulltext') { // $getfields[] = 'relevance'; //} $count = 0; // TODO: allow combination of searches ? foreach ($ptids as $curptid) { $publications = xarModAPIFunc('publications', 'user', 'getall', array('startnum' => $startnum, 'cids' => $cids, 'andcids' => $andcids, 'ptid' => $curptid, 'owner' => $owner, 'sort' => $sort, 'numitems' => $numitems, 'state' => $state, 'start_date' => $startdate, 'end_date' => $enddate, 'searchfields' => $fieldlist, 'searchtype' => $searchtype, 'search' => $q, 'fields' => $getfields)); // TODO: re-use article output code from elsewhere (view / archive / admin) if (!empty($publications) && count($publications) > 0) { // retrieve the categories for each article $catinfo = array(); if ($show_categories) { $cidlist = array(); foreach ($publications as $article) { if (!empty($article['cids']) && count($article['cids']) > 0) { foreach ($article['cids'] as $cid) { $cidlist[$cid] = 1; } } } if (count($cidlist) > 0) { $catinfo = xarModAPIFunc('categories', 'user', 'getcatinfo', array('cids' => array_keys($cidlist))); // get root categories for this publication type $catroots = xarModAPIFunc('publications', 'user', 'getrootcats', array('ptid' => $curptid)); $catroots = xarModAPIFunc('categories', 'user', 'getallcatbases', array('module' => 'publications', 'itemtype' => $curptid)); } foreach ($catinfo as $cid => $info) { $catinfo[$cid]['name'] = xarVarPrepForDisplay($info['name']); $catinfo[$cid]['link'] = xarModURL('publications', 'user', 'view', array('ptid' => $curptid, 'catid' => $catid && $andcids ? $catid . '+' . $cid : $cid)); // only needed when sorting by root category id $catinfo[$cid]['root'] = 0; // means not found under a root category // only needed when sorting by root category order $catinfo[$cid]['order'] = 0; // means not found under a root category $rootidx = 1; foreach ($catroots as $rootcat) { // see if we're a child category of this rootcat (cfr. Celko model) if ($info['left'] >= $rootcat['left_id'] && $info['left'] < $rootcat['right_id']) { // only needed when sorting by root category id $catinfo[$cid]['root'] = $rootcat['category_id']; // only needed when sorting by root category order $catinfo[$cid]['order'] = $rootidx; break; } $rootidx++; } } } // needed for sort function below $GLOBALS['artsearchcatinfo'] = $catinfo; $items = array(); foreach ($publications as $article) { $count++; $curptid = $article['pubtype_id']; $link = xarModURL('publications', 'user', 'display', array('ptid' => $article['pubtype_id'], 'itemid' => $article['id'])); // publication date of article (if needed) if (!empty($pubtypes[$curptid]['config']['startdate']['label']) && !empty($article['startdate'])) { $date = xarLocaleFormatDate('%a, %d %B %Y %H:%M:%S %Z', $article['startdate']); $startdate = $article['startdate']; } else { $date = ''; $startdate = 0; } if (empty($article['title'])) { $article['title'] = xarML('(none)'); } // categories this article belongs to $categories = array(); if ($show_categories && !empty($article['cids']) && is_array($article['cids']) && count($article['cids']) > 0) { $cidlist = $article['cids']; // order cids by root category order usort($cidlist, 'publications_search_sortbyorder'); // order cids by root category id //usort($cidlist,'publications_search_sortbyroot'); // order cids by position in Celko tree //usort($cidlist,'publications_search_sortbyleft'); $join = ''; foreach ($cidlist as $cid) { $item = array(); if (!isset($catinfo[$cid])) { // oops continue; } $categories[] = array('cname' => $catinfo[$cid]['name'], 'clink' => $catinfo[$cid]['link'], 'cjoin' => $join); if (empty($join)) { $join = ' | '; } } } $items[] = array('title' => xarVarPrepHTMLDisplay($article['title']), 'link' => $link, 'date' => $date, 'startdate' => $startdate, 'relevance' => isset($article['relevance']) ? $article['relevance'] : null, 'categories' => $categories); } unset($publications); // Pager // TODO: make count depend on locale in the future sys::import('modules.base.class.pager'); $pager = xarTplPager::getPager($startnum, xarModAPIFunc('publications', 'user', 'countitems', array('cids' => $cids, 'andcids' => $andcids, 'ptid' => $curptid, 'owner' => $owner, 'state' => $state, 'startdate' => $startdate, 'enddate' => $enddate, 'searchfields' => $fieldlist, 'searchtype' => $searchtype, 'search' => $q)), xarModURL('publications', 'user', 'search', array('ptid' => $curptid, 'catid' => $catid, 'q' => isset($q) ? $q : null, 'author' => isset($author) ? $author : null, 'start' => $startdate, 'end' => $enddate != $now ? $enddate : null, 'state' => $stateline, 'sort' => $sort, 'fields' => $fields, 'searchtype' => !empty($searchtype) ? $searchtype : null, 'startnum' => '%%')), $numitems); if (strlen($pager) > 5) { if (!isset($sort) || $sort == 'date') { $othersort = 'title'; } else { $othersort = null; } $sortlink = xarModURL('publications', 'user', 'search', array('ptid' => $curptid, 'catid' => $catid, 'q' => isset($q) ? $q : null, 'author' => isset($author) ? $author : null, 'start' => $startdate, 'end' => $enddate != $now ? $enddate : null, 'state' => $stateline, 'fields' => $fields, 'searchtype' => !empty($searchtype) ? $searchtype : null, 'sort' => $othersort)); if (!isset($othersort)) { $othersort = 'date'; } $pager .= '  <a href="' . $sortlink . '">' . xarML('sort by') . ' ' . xarML($othersort) . '</a>'; } $data['results'][] = array('description' => xarVarPrepForDisplay($pubtypes[$curptid]['description']), 'items' => $items, 'pager' => $pager); } } unset($catinfo); unset($items); unset($GLOBALS['artsearchcatinfo']); if ($count > 0) { // bail out, we have what we needed return xarTplModule('publications', 'user', 'search', $data); } $data['state'] = xarML('No pages found matching this search'); } return xarTplModule('publications', 'user', 'search', $data); }
/** * check security for a particular article * * @param $args['mask'] the requested security mask * * @param $args['article'] the article array (if already retrieved) * @param $args['id'] the article ID (if known, and article array not already retrieved) * @param $args['owner'] the user ID of the author (if not already included) * @param $args['ptid'] the publication type ID (if not already included) * @param $args['cids'] array of additional required category checks * * @return bool true if OK, false if not OK */ function publications_userapi_checksecurity($args) { // Get arguments from argument array extract($args); // Compatibility mode with old API params - remove later if (isset($access) && !isset($mask)) { switch ($access) { case ACCESS_OVERVIEW: $mask = 'ViewPublications'; break; case ACCESS_READ: $mask = 'ReadPublications'; break; case ACCESS_COMMENT: $mask = 'SubmitPublications'; break; case ACCESS_EDIT: $mask = 'EditPublications'; break; case ACCESS_DELETE: $mask = 'ManagePublications'; break; case ACCESS_ADMIN: $mask = 'AdminPublications'; break; default: $mask = ''; } } if (empty($mask)) { return false; } // Get article information if (!isset($publication) && !empty($id) && $mask != 'SubmitPublications') { $publication = xarModAPIFunc('publications', 'user', 'get', array('id' => $id, 'withcids' => true)); if ($publication == false) { return false; } } if (empty($id) && isset($publication['id'])) { $id = $publication['id']; } if (!isset($id)) { $id = ''; } // Get author ID if (isset($publication['owner']) && empty($owner)) { $owner = $publication['owner']; } // Get state if (isset($publication['state']) && !isset($state)) { $state = $publication['state']; } if (empty($state)) { $state = 0; } // reject reading access to unapproved publications if ($state < 2 && ($mask == 'ViewPublications' || $mask == 'ReadPublications')) { return false; } // Get publication type ID if (isset($publication['pubtype_id'])) { if (!isset($ptid)) { $ptid = $publication['pubtype_id']; } elseif ($ptid != $publication['pubtype_id'] && $mask != 'EditPublications') { return false; } } // Get root categories for this publication type if (!empty($ptid)) { $rootcats = xarModAPIFunc('categories', 'user', 'getallcatbases', array('module' => 'publications', 'itemtype' => $ptid)); } else { $ptid = null; } if (!isset($rootcids)) { // TODO: handle cross-pubtype views better $rootcats = xarModAPIFunc('categories', 'user', 'getallcatbases', array('module' => 'publications')); } // Get category information for this article if (!isset($publication['cids']) && !empty($id)) { if (!xarModAPILoad('categories', 'user')) { return; } $info = xarMod::getBaseInfo('publications'); $sysid = $info['systemid']; $publicationcids = xarModAPIFunc('categories', 'user', 'getlinks', array('iids' => array($id), 'itemtype' => $ptid, 'modid' => $sysid, 'reverse' => 0)); if (is_array($publicationcids) && count($publicationcids) > 0) { $publication['cids'] = array_keys($publicationcids); } } if (!isset($publication['cids'])) { $publication['cids'] = array(); } if (!isset($cids)) { $cids = array(); } $jointcids = array(); /* TODO: forget about parent/root cids for now foreach ($rootcids as $cid) { $jointcids[$cid] = 1; } */ foreach ($publication['cids'] as $cid) { $jointcids[$cid] = 1; } // FIXME: the line within the foreach is known to give an illegal offset error, not sure how to properly // fix it. Only seen on using xmlrpc and bloggerapi. foreach ($cids as $cid) { if (empty($cid) || !is_numeric($cid)) { continue; } $jointcids[$cid] = 1; } // TODO 1: find a way to combine checking over several categories // TODO 2: find a way to check parent categories for privileges too // TODO 3: find a way to specify current user in privileges too // TODO 4: find a way to check parent groups of authors for privileges too ?? if (empty($ptid)) { $ptid = 'All'; } if (count($jointcids) == 0) { $jointcids['All'] = 1; } // TODO: check for anonymous publications if (!isset($owner)) { $owner = 'All'; } if (empty($id)) { $id = 'All'; } // Loop over all categories and check the different combinations $result = false; foreach (array_keys($jointcids) as $cid) { // TODO: do we want all-or-nothing access here, or is one access enough ? if (xarSecurityCheck($mask, 0, 'Publication', "{$ptid}:{$cid}:{$owner}:{$id}")) { $result = true; } } return $result; }
/** * get an array of root categories with links * * @param int $args['ptid'] publication type ID * @param $args['all'] boolean if we need to return all root categories when * ptid is empty (default false) * @return array * @TODO specify return format */ function publications_userapi_getrootcats($args) { extract($args); if (empty($ptid) || !is_numeric($ptid)) { $ptid = null; } // see which root categories we need to handle $rootcats = array(); if (!empty($ptid)) { $rootcats = unserialize(xarModUserVars::get('publications', 'basecids', $ptid)); } elseif (empty($all)) { $rootcats = unserialize(xarModVars::get('publications', 'basecids')); } else { // Get publication types $pubtypes = xarModAPIFunc('publications', 'user', 'get_pubtypes'); // get base categories for all publication types here $publist = array_keys($pubtypes); // add the defaults too, in case we have other base categories there $publist[] = ''; // build the list of root categories for all required publication types $catlist = array(); foreach ($publist as $pubid) { if (empty($pubid)) { $cidstring = xarModVars::get('publications', 'basecids'); } else { $cidstring = xarModUserVars::get('publications', 'basecids', $pubid); } if (!empty($cidstring)) { $rootcats = unserialize($cidstring); } else { $rootcats = array(); } foreach ($rootcats as $cid) { $catlist[$cid] = 1; } } if (count($catlist) > 0) { $rootcats = array_keys($catlist); } } if (empty($rootcats)) { $rootcats = array(); } if (count($rootcats) < 1) { return array(); } if (!xarModAPILoad('categories', 'user')) { return; } $isfirst = 1; $catlinks = array(); $catlist = xarModAPIFunc('categories', 'user', 'getcatinfo', array('cids' => $rootcats)); if (empty($catlist)) { return $catlinks; } // preserve order of root categories if possible foreach ($rootcats as $cid) { if (!isset($catlist[$cid])) { continue; } $info = $catlist[$cid]; $item = array(); $item['catid'] = $info['cid']; $item['cattitle'] = xarVarPrepForDisplay($info['name']); $item['catlink'] = xarModURL('publications', 'user', 'view', array('ptid' => $ptid, 'catid' => $info['cid'])); if ($isfirst) { $item['catjoin'] = ''; $isfirst = 0; } else { $item['catjoin'] = ' | '; } $item['catleft'] = $info['left']; $item['catright'] = $info['right']; $catlinks[] = $item; } return $catlinks; }
/** * show monthly archive (Archives-like) */ function publications_user_archive($args) { // Get parameters from user if (!xarVarFetch('ptid', 'id', $ptid, xarModVars::get('publications', 'defaultpubtype'), XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('sort', 'enum:d:t:1:2', $sort, 'd', XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('month', 'str', $month, '', XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('cids', 'array', $cids, NULL, XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('catid', 'str', $catid, '', XARVAR_NOT_REQUIRED)) { return; } // Override if needed from argument array extract($args); // Get publication types $pubtypes = xarModAPIFunc('publications', 'user', 'get_pubtypes'); // Check that the publication type is valid if (empty($ptid) || !isset($pubtypes[$ptid])) { $ptid = null; } if (empty($ptid)) { if (!xarSecurityCheck('ViewPublications', 0, 'Publication', 'All:All:All:All')) { return xarML('You have no permission to view these items'); } } elseif (!xarSecurityCheck('ViewPublications', 0, 'Publication', $ptid . ':All:All:All')) { return xarML('You have no permission to view these items'); } $state = array(PUBLICATIONS_STATE_FRONTPAGE, PUBLICATIONS_STATE_APPROVED); $seencid = array(); $andcids = false; // turn $catid into $cids array and set $andcids flag if (!empty($catid)) { if (strpos($catid, ' ')) { $cids = explode(' ', $catid); $andcids = true; } elseif (strpos($catid, '+')) { $cids = explode('+', $catid); $andcids = true; } elseif (strpos($catid, '-')) { $cids = explode('-', $catid); $andcids = false; } else { $cids = array($catid); if (strstr($catid, '_')) { $andcids = false; // don't combine with current category } else { $andcids = true; } } } if (isset($cids) && is_array($cids)) { foreach ($cids as $cid) { if (!empty($cid) && preg_match('/^_?[0-9]+$/', $cid)) { $seencid[$cid] = 1; } } $cids = array_keys($seencid); sort($cids, SORT_NUMERIC); if (empty($catid) && count($cids) > 1) { $andcids = true; } } else { $cids = null; } // QUESTION: work with user-dependent time settings or not someday ? // Set the start and end date for that month if (!empty($month) && preg_match('/^(\\d{4})-(\\d+)$/', $month, $matches)) { $startdate = gmmktime(0, 0, 0, $matches[2], 1, $matches[1]); // PHP allows month > 12 :-) $enddate = gmmktime(0, 0, 0, $matches[2] + 1, 1, $matches[1]); if ($enddate > time()) { $enddate = time(); } } else { $startdate = ''; $enddate = time(); if (!empty($month) && $month != 'all') { $month = ''; } } // Load API if (!xarModAPILoad('publications', 'user')) { return; } if (!empty($ptid) && !empty($pubtypes[$ptid]['config']['pubdate']['label'])) { $showdate = 1; } else { $showdate = 0; foreach (array_keys($pubtypes) as $pubid) { if (!empty($pubtypes[$pubid]['config']['pubdate']['label'])) { $showdate = 1; break; } } } // Get monthly statistics $monthcount = xarModAPIFunc('publications', 'user', 'getmonthcount', array('ptid' => $ptid, 'state' => $state, 'enddate' => time())); if (empty($monthcount)) { $monthcount = array(); } krsort($monthcount); reset($monthcount); $months = array(); $total = 0; foreach ($monthcount as $thismonth => $count) { if ($thismonth == $month) { $mlink = ''; } else { $mlink = xarModURL('publications', 'user', 'archive', array('ptid' => $ptid, 'month' => $thismonth)); } $months[] = array('month' => $thismonth, 'mcount' => $count, 'mlink' => $mlink); $total += $count; } if (empty($ptid)) { $thismonth = xarML('All Publications'); } else { $thismonth = xarML('All') . ' ' . $pubtypes[$ptid]['description']; } if ($month == 'all') { $mlink = ''; } else { $mlink = xarModURL('publications', 'user', 'archive', array('ptid' => $ptid, 'month' => 'all')); } $months[] = array('month' => $thismonth, 'mcount' => $total, 'mlink' => $mlink); // Load API if (!xarModAPILoad('categories', 'user')) { return; } // Get the list of root categories for this publication type if (!empty($ptid)) { $rootcats = xarModAPIFunc('categories', 'user', 'getallcatbases', array('module' => 'publications', 'itemtype' => $ptid)); } else { $rootcats = xarModAPIFunc('categories', 'user', 'getallcatbases', array('module' => 'publications', 'itemtype' => 0)); } $catlist = array(); $catinfo = array(); $catsel = array(); if (!empty($rootcats)) { // TODO: do this in categories API ? $count = 1; foreach ($rootcats as $cid) { if (empty($cid)) { continue; } // save the name and root category for each child $cats = xarModAPIFunc('categories', 'user', 'getcat', array('cid' => $cid['category_id'], 'return_itself' => true, 'getchildren' => true)); foreach ($cats as $info) { $item = array(); $item['name'] = $info['name']; $item['root'] = $cid['category_id']; $catinfo[$info['cid']] = $item; } // don't allow sorting by category when viewing all publications //if ($sort == $count || $month == 'all') { if ($sort == $count) { $link = ''; } else { $link = xarModURL('publications', 'user', 'archive', array('ptid' => $ptid, 'month' => $month, 'sort' => $count)); } // catch more faulty categories assignments if (isset($catinfo[$cid['category_id']])) { $catlist[] = array('cid' => $cid['category_id'], 'name' => $catinfo[$cid['category_id']]['name'], 'link' => $link); $catsel[] = xarModAPIFunc('categories', 'visual', 'makeselect', array('cid' => $cid['category_id'], 'return_itself' => true, 'select_itself' => true, 'values' => &$seencid, 'multiple' => 0)); $count++; } } } // Get publications if ($month == 'all' || $startdate && $enddate) { $publications = xarModAPIFunc('publications', 'user', 'getall', array('ptid' => isset($ptid) ? $ptid : null, 'startdate' => $startdate, 'enddate' => $enddate, 'state' => $state, 'cids' => $cids, 'andcids' => $andcids, 'fields' => array('id', 'title', 'start_date', 'pubtype_id', 'cids'))); if (!is_array($publications)) { $msg = xarML('Failed to retrieve publications in #(3)_#(1)_#(2).php', 'user', 'getall', 'publications'); throw new DataNotFoundException(null, $msg); } } else { $publications = array(); } // TODO: add print / recommend_us link for each article ? // TODO: add view count to table/query/template someday ? foreach ($publications as $key => $article) { $publications[$key]['link'] = xarModURL('publications', 'user', 'display', array('ptid' => isset($ptid) ? $publications[$key]['pubtype_id'] : null, 'id' => $publications[$key]['id'])); if (empty($publications[$key]['title'])) { $publications[$key]['title'] = xarML('(none)'); } /* TODO: move date formatting to template, delete this code after testing if ($showdate && !empty($publications[$key]['pubdate'])) { $publications[$key]['date'] = xarLocaleFormatDate("%Y-%m-%d %H:%M:%S", $publications[$key]['pubdate']); } else { $publications[$key]['date'] = ''; } */ // TODO: find some better way to do this... $list = array(); // get all the categories for that article and put them under the // right root category if (!isset($publications[$key]['cids'])) { $publications[$key]['cids'] = array(); } foreach ($publications[$key]['cids'] as $cid) { // skip unknown categories (e.g. when not under root categories) if (!isset($catinfo[$cid])) { continue; } if (!isset($list[$catinfo[$cid]['root']])) { $list[$catinfo[$cid]['root']] = array(); } array_push($list[$catinfo[$cid]['root']], $cid); } // fill in the column corresponding to each root category $publications[$key]['cats'] = array(); foreach ($catlist as $cat) { if (isset($list[$cat['cid']])) { $descr = ''; // TODO: add links to category someday ? foreach ($list[$cat['cid']] as $cid) { if (!empty($descr)) { $descr .= '<br />'; } $descr .= $catinfo[$cid]['name']; } $publications[$key]['cats'][] = array('list' => $descr); } else { $publications[$key]['cats'][] = array('list' => '-'); } } } // sort publications as requested if ($sort == 2 && count($catlist) > 1) { usort($publications, 'publications_archive_sortbycat10'); } elseif ($sort == 1) { if (count($catlist) > 1) { usort($publications, 'publications_archive_sortbycat01'); } elseif (count($catlist) > 0) { usort($publications, 'publications_archive_sortbycat0'); } } elseif ($sort == 't') { usort($publications, 'publications_archive_sortbytitle'); } else { $sort = 'd'; // default sort by date is already done in getall() function } // add title header if ($sort == 't') { $link = ''; } else { $link = xarModURL('publications', 'user', 'archive', array('ptid' => $ptid, 'month' => $month, 'sort' => 't')); } $catlist[] = array('cid' => 0, 'name' => xarML('Title'), 'link' => $link); $catsel[] = '<input type="submit" value="' . xarML('Filter') . '" />'; if ($showdate) { // add date header if ($sort == 'd') { $link = ''; } else { $link = xarModURL('publications', 'user', 'archive', array('ptid' => $ptid, 'month' => $month)); } $catlist[] = array('cid' => 0, 'name' => xarML('Date'), 'link' => $link); $catsel[] = ' '; } // Save some variables to (temporary) cache for use in blocks etc. xarVarSetCached('Blocks.publications', 'ptid', $ptid); if (!empty($cids)) { xarVarSetCached('Blocks.publications', 'cids', $cids); } //if ($shownavigation) { xarVarSetCached('Blocks.categories', 'module', 'publications'); xarVarSetCached('Blocks.categories', 'itemtype', $ptid); if (!empty($ptid) && !empty($pubtypes[$ptid]['description'])) { xarVarSetCached('Blocks.categories', 'title', $pubtypes[$ptid]['description']); xarTplSetPageTitle(xarML('Archive'), $pubtypes[$ptid]['description']); } else { xarTplSetPageTitle(xarML('Archive')); } //} if (!empty($ptid)) { $settings = unserialize(xarModVars::get('publications', 'settings.' . $ptid)); } else { $string = xarModVars::get('publications', 'settings'); if (!empty($string)) { $settings = unserialize($string); } } if (!isset($show_publinks)) { if (!empty($settings['show_publinks'])) { $show_publinks = 1; } else { $show_publinks = 0; } } // show the number of publications for each publication type if (!isset($show_pubcount)) { if (!isset($settings['show_pubcount']) || !empty($settings['show_pubcount'])) { $show_pubcount = 1; // default yes } else { $show_pubcount = 0; } } // $show_catcount = 0; // unused here // return template out $data = array('months' => $months, 'publications' => $publications, 'catlist' => $catlist, 'catsel' => $catsel, 'ptid' => $ptid, 'month' => $month, 'curlink' => xarModURL('publications', 'user', 'archive', array('ptid' => $ptid, 'month' => $month, 'sort' => $sort)), 'showdate' => $showdate, 'show_publinks' => $show_publinks, 'publabel' => xarML('Publication'), 'publinks' => xarModAPIFunc('publications', 'user', 'getpublinks', array('ptid' => $ptid, 'state' => array(PUBLICATIONS_STATE_FRONTPAGE, PUBLICATIONS_STATE_APPROVED), 'count' => $show_pubcount, 'func' => 'archive')), 'maplabel' => xarML('View Publication Map'), 'maplink' => xarModURL('publications', 'user', 'viewmap', array('ptid' => $ptid)), 'viewlabel' => empty($ptid) ? xarML('Back to Publications') : xarML('Back to') . ' ' . $pubtypes[$ptid]['description'], 'viewlink' => xarModURL('publications', 'user', 'view', array('ptid' => $ptid))); if (!empty($ptid)) { $template = $pubtypes[$ptid]['name']; } else { // TODO: allow templates per category ? $template = null; } return xarTplModule('publications', 'user', 'archive', $data, $template); }
/** * get an array of child categories with links and optional counts * * @param $args['state'] array of requested status(es) for the publications * @param $args['ptid'] publication type ID * @param $args['cid'] parent category ID * @param $args['showcid'] false (default) means skipping the parent cid * @param $args['count'] true (default) means counting the number of publications * @param $args['filter'] additional categories we're filtering on (= catid) * @return array */ function publications_userapi_getchildcats($args) { extract($args); if (!isset($cid) || !is_numeric($cid)) { return array(); } if (empty($ptid)) { $ptid = null; } if (!isset($state)) { // frontpage or approved $state = array(PUBLICATIONS_STATE_FRONTPAGE, PUBLICATIONS_STATE_APPROVED); } if (!isset($showcid)) { $showcid = false; } if (!isset($count)) { $count = true; } if (!isset($filter)) { $filter = ''; } if (!xarModAPILoad('categories', 'visual')) { return; } // TODO: make sure permissions are taken into account here ! $list = xarModAPIFunc('categories', 'visual', 'listarray', array('cid' => $cid)); // get the counts for all child categories if ($count) { if (empty($filter)) { $seencid = array(); foreach ($list as $info) { $seencid[$info['id']] = 1; } $childlist = array_keys($seencid); $andcids = false; } else { // we'll combine the parent cid with the filter here $childlist = array('_' . $cid, $filter); $andcids = true; } $pubcatcount = xarModAPIFunc('publications', 'user', 'getpubcatcount', array('state' => array(PUBLICATIONS_STATE_FRONTPAGE, PUBLICATIONS_STATE_APPROVED), 'cids' => $childlist, 'andcids' => $andcids, 'ptid' => $ptid, 'reverse' => 1)); if (!empty($ptid)) { $curptid = $ptid; } else { $curptid = 'total'; } } $cats = array(); foreach ($list as $info) { if ($info['id'] == $cid && !$showcid) { continue; } if (!empty($filter)) { $catid = $filter . '+' . $info['id']; } else { $catid = $info['id']; } // TODO: show icons instead of (or in addition to) a link if available ? $info['link'] = xarModURL('publications', 'user', 'view', array('ptid' => $ptid, 'catid' => $catid)); $info['name'] = xarVarPrepForDisplay($info['name']); if ($count) { if (isset($pubcatcount[$info['id']][$curptid])) { $info['count'] = $pubcatcount[$info['id']][$curptid]; } elseif (!empty($filter) && isset($pubcatcount[$filter . '+' . $info['id']][$curptid])) { $info['count'] = $pubcatcount[$filter . '+' . $info['id']][$curptid]; } elseif (!empty($filter) && isset($pubcatcount[$info['id'] . '+' . $filter][$curptid])) { $info['count'] = $pubcatcount[$info['id'] . '+' . $filter][$curptid]; } else { $info['count'] = ''; } } else { $info['count'] = ''; } $cats[] = $info; } return $cats; }
/** * get a list of article authors depending on additional module criteria * * @param $args['cids'] array of cids that we are counting for (OR/AND) * @param $args['andcids'] true means AND-ing categories listed in cids * * @param $args['owner'] the ID of the author * @param $args['ptid'] publication type ID (for news, sections, reviews, ...) * @param $args['state'] array of requested status(es) for the publications * @param $args['startdate'] publications published at startdate or later * (unix timestamp format) * @param $args['enddate'] publications published before enddate * (unix timestamp format) * @return array of author id => author name */ function publications_userapi_getauthors($args) { // Database information $dbconn = xarDB::getConn(); // Get the field names and LEFT JOIN ... ON ... parts from publications // By passing on the $args, we can let leftjoin() create the WHERE for // the publications-specific columns too now $publicationsdef = xarModAPIFunc('publications', 'user', 'leftjoin', $args); // Load API if (!xarModAPILoad('roles', 'user')) { return; } // Get the field names and LEFT JOIN ... ON ... parts from users $usersdef = xarModAPIFunc('roles', 'user', 'leftjoin'); // TODO: make sure this is SQL standard // Start building the query $query = 'SELECT DISTINCT ' . $publicationsdef['owner'] . ', ' . $usersdef['name']; $query .= ' FROM ' . $publicationsdef['table']; // Add the LEFT JOIN ... ON ... parts from users $query .= ' LEFT JOIN ' . $usersdef['table']; $query .= ' ON ' . $usersdef['field'] . ' = ' . $publicationsdef['owner']; if (!isset($args['cids'])) { $args['cids'] = array(); } if (!isset($args['andcids'])) { $args['andcids'] = false; } if (count($args['cids']) > 0) { // Load API if (!xarModAPILoad('categories', 'user')) { return; } // Get the LEFT JOIN ... ON ... and WHERE (!) parts from categories $args['modid'] = xarModGetIDFromName('publications'); if (isset($args['ptid']) && !isset($args['itemtype'])) { $args['itemtype'] = $args['ptid']; } $categoriesdef = xarModAPIFunc('categories', 'user', 'leftjoin', $args); $query .= ' LEFT JOIN ' . $categoriesdef['table']; $query .= ' ON ' . $categoriesdef['field'] . ' = ' . $publicationsdef['id']; $query .= $categoriesdef['more']; $docid = 1; } // Create the WHERE part $where = array(); // we rely on leftjoin() to create the necessary publications clauses now if (!empty($publicationsdef['where'])) { $where[] = $publicationsdef['where']; } if (!empty($docid)) { // we rely on leftjoin() to create the necessary categories clauses $where[] = $categoriesdef['where']; } if (count($where) > 0) { $query .= ' WHERE ' . join(' AND ', $where); } // Order by author name $query .= ' ORDER BY ' . $usersdef['name'] . ' ASC'; // Run the query - finally :-) $result =& $dbconn->Execute($query); if (!$result) { return; } $authors = array(); while (!$result->EOF) { list($uid, $name) = $result->fields; $authors[$uid] = array('id' => $uid, 'name' => $name); $result->MoveNext(); } $result->Close(); return $authors; }
/** * Update a publication type * * @param id $args['ptid'] ID of the publication type * @param string $args['name'] name of the publication type (not allowed here) * @param string $args['description'] description of the publication type * @param array $args['config'] configuration of the publication type * @return bool true on success, false on failure */ function publications_adminapi_updatepubtype($args) { // Get arguments from argument array extract($args); // Argument check - make sure that all required arguments are present // and in the right format, if not then set an appropriate error // message and return // Note : since we have several arguments we want to check here, we'll // report all those that are invalid at the same time... $invalid = array(); if (!isset($ptid) || !is_numeric($ptid) || $ptid < 1) { $invalid[] = 'publication type ID'; } /* if (!isset($name) || !is_string($name) || empty($name)) { $invalid[] = 'name'; } */ if (!isset($descr) || !is_string($descr) || empty($descr)) { $invalid[] = 'description'; } if (!isset($config) || !is_array($config) || count($config) == 0) { $invalid[] = 'configuration'; } if (count($invalid) > 0) { $msg = xarML('Invalid #(1) for #(2) function #(3)() in module #(4)', join(', ', $invalid), 'admin', 'updatepubtype', 'Publications'); throw new BadParameterException(null, $msg); } // Security check - we require ADMIN rights here if (!xarSecurityCheck('AdminPublications', 1, 'Publication', "{$ptid}:All:All:All")) { return; } // Load user API to obtain item information function if (!xarModAPILoad('publications', 'user')) { return; } // Get current publication types $pubtypes = xarModAPIFunc('publications', 'user', 'get_pubtypes'); if (!isset($pubtypes[$ptid])) { $msg = xarML('Invalid #(1) for #(2) function #(3)() in module #(4)', 'publication type ID', 'admin', 'updatepubtype', 'Publications'); throw new BadParameterException(null, $msg); } // Make sure we have all the configuration fields we need $pubfields = xarModAPIFunc('publications', 'user', 'getpubfields'); foreach ($pubfields as $field => $value) { if (!isset($config[$field])) { $config[$field] = ''; } } // Get database setup $dbconn = xarDB::getConn(); $xartable = xarDB::getTables(); $pubtypestable = $xartable['publication_types']; // Update the publication type (don't allow updates on name) $query = "UPDATE {$pubtypestable}\n SET pubtypedescr = ?,\n pubtypeconfig = ?\n WHERE pubtype_id = ?"; $bindvars = array($descr, serialize($config), $ptid); $result =& $dbconn->Execute($query, $bindvars); if (!$result) { return; } return true; }
/** * get overview of all publications * Note : the following parameters are all optional * * @param $args['numitems'] number of publications to get * @param $args['sort'] sort order ('create_date','title','hits','rating','author','id','summary','notes',...) * @param $args['startnum'] starting article number * @param $args['ids'] array of article ids to get * @param $args['owner'] the ID of the author * @param $args['ptid'] publication type ID (for news, sections, reviews, ...) * @param $args['state'] array of requested status(es) for the publications * @param $args['search'] search parameter(s) * @param $args['searchfields'] array of fields to search in * @param $args['searchtype'] start, end, like, eq, gt, ... (TODO) * @param $args['cids'] array of category IDs for which to get publications (OR/AND) * (for all categories don?t set it) * @param $args['andcids'] true means AND-ing categories listed in cids * @param $args['create_date'] publications published in a certain year (YYYY), month (YYYY-MM) or day (YYYY-MM-DD) * @param $args['startdate'] publications published at startdate or later * (unix timestamp format) * @param $args['enddate'] publications published before enddate * (unix timestamp format) * @param $args['fields'] array with all the fields to return per publication * Default list is : 'id','title','summary','owner', * 'create_date','pubtype_id','notes','state','body1' * Optional fields : 'cids','author','counter','rating','dynamicdata' * @param $args['extra'] array with extra fields to return per article (in addition * to the default list). So you can EITHER specify *all* the * fields you want with 'fields', OR take all the default * ones and add some optional fields with 'extra' * @param $args['where'] additional where clauses (e.g. myfield gt 1234) * @param $args['locale'] language/locale (if not using multi-sites, categories etc.) * @return array Array of publications, or false on failure */ function publications_userapi_getall($args) { // Get arguments from argument array extract($args); // Optional argument if (!isset($startnum)) { $startnum = 1; } if (empty($cids)) { $cids = array(); } if (!isset($andcids)) { $andcids = false; } if (empty($ptid)) { $ptid = null; } // Default fields in publications (for now) $columns = array('id', 'name', 'title', 'description', 'summary', 'body1', 'owner', 'pubtype_id', 'notes', 'state', 'start_date'); // Optional fields in publications (for now) // + 'cids' = list of categories an article belongs to // + 'author' = user name of owner // + 'counter' = number of times this article was displayed (hitcount) // + 'rating' = rating for this article (ratings) // + 'dynamicdata' = dynamic data fields for this article (dynamicdata) // + 'relevance' = relevance for this article (MySQL full-text search only) // $optional = array('cids','author','counter','rating','dynamicdata','relevance'); if (!isset($fields)) { $fields = $columns; } if (isset($extra) && is_array($extra) && count($extra) > 0) { $fields = array_merge($fields, $extra); } if (empty($sort)) { if (!empty($search) && !empty($searchtype) && substr($searchtype, 0, 8) == 'fulltext') { if ($searchtype == 'fulltext boolean' && !in_array('relevance', $fields)) { // add the relevance to the field list for sorting $fields[] = 'relevance'; } // let the database sort by relevance (= default for fulltext) $sortlist = array(); } else { // default sort by create_date $sortlist = array('create_date'); } } elseif (is_array($sort)) { $sortlist = $sort; } else { $sortlist = explode(',', $sort); } $publications = array(); // Security check if (!xarSecurityCheck('ViewPublications')) { return; } // Fields requested by the calling function $required = array(); foreach ($fields as $field) { $required[$field] = 1; } // mandatory fields for security $required['id'] = 1; $required['title'] = 1; $required['pubtype_id'] = 1; $required['create_date'] = 1; $required['owner'] = 1; // not to be confused with author (name) :-) // force cids as required when categories are given if (count($cids) > 0) { $required['cids'] = 1; } // TODO: put all this in dynamic data and retrieve everything via there (including hooked stuff) // Database information $dbconn = xarDB::getConn(); // Get the field names and LEFT JOIN ... ON ... parts from publications // By passing on the $args, we can let leftjoin() create the WHERE for // the publications-specific columns too now $publicationsdef = xarModAPIFunc('publications', 'user', 'leftjoin', $args); // TODO : how to handle the case where name is empty, but uname isn't if (!empty($required['owner'])) { // Load API if (!xarModAPILoad('roles', 'user')) { return; } // Get the field names and LEFT JOIN ... ON ... parts from users $usersdef = xarModAPIFunc('roles', 'user', 'leftjoin'); if (empty($usersdef)) { return; } } $regid = xarMod::getRegID('publications'); if (!empty($required['cids'])) { // Load API if (!xarModAPILoad('categories', 'user')) { return; } // Get the LEFT JOIN ... ON ... and WHERE (!) parts from categories $categoriesdef = xarModAPIFunc('categories', 'user', 'leftjoin', array('cids' => $cids, 'andcids' => $andcids, 'itemtype' => isset($ptid) ? $ptid : null, 'modid' => $regid)); if (empty($categoriesdef)) { return; } } if (!empty($required['counter']) && xarModIsHooked('hitcount', 'publications', $ptid)) { // Load API if (!xarModAPILoad('hitcount', 'user')) { return; } // Get the LEFT JOIN ... ON ... and WHERE (!) parts from hitcount $hitcountdef = xarModAPIFunc('hitcount', 'user', 'leftjoin', array('modid' => $regid, 'itemtype' => isset($ptid) ? $ptid : null)); } if (!empty($required['rating']) && xarModIsHooked('ratings', 'publications', $ptid)) { // Load API if (!xarModAPILoad('ratings', 'user')) { return; } // Get the LEFT JOIN ... ON ... and WHERE (!) parts from ratings $ratingsdef = xarModAPIFunc('ratings', 'user', 'leftjoin', array('modid' => $regid, 'itemtype' => isset($ptid) ? $ptid : null)); } // Create the SELECT part $select = array(); foreach ($required as $field => $val) { // we'll handle this later if ($field == 'cids') { continue; } elseif ($field == 'dynamicdata') { continue; } elseif ($field == 'owner') { $select[] = $usersdef['name']; } elseif ($field == 'counter') { if (!empty($hitcountdef['hits'])) { $select[] = $hitcountdef['hits']; } } elseif ($field == 'rating') { if (!empty($ratingsdef['rating'])) { $select[] = $ratingsdef['rating']; } } else { $select[] = $publicationsdef[$field]; } } // FIXME: <rabbitt> PostgreSQL requires that all fields in an 'Order By' be in the SELECT // this has been added to remove the error that not having it creates // FIXME: <mikespub> Oracle doesn't allow having the same field in a query twice if you // don't specify an alias (at least in sub-queries, which is what SelectLimit uses) // if (!in_array($publicationsdef['create_date'], $select)) { // $select[] = $publicationsdef['create_date']; // } // we need distinct for multi-category OR selects where publications fit in more than 1 category if (count($cids) > 0) { $query = 'SELECT DISTINCT ' . join(', ', $select); } else { $query = 'SELECT ' . join(', ', $select); } // Create the FROM ... [LEFT JOIN ... ON ...] part $from = $publicationsdef['table']; $addme = 0; if (!empty($required['owner'])) { // Add the LEFT JOIN ... ON ... parts from users $from .= ' LEFT JOIN ' . $usersdef['table']; $from .= ' ON ' . $usersdef['field'] . ' = ' . $publicationsdef['owner']; $addme = 1; } if (!empty($required['counter']) && isset($hitcountdef)) { // add this for SQL compliance when there are multiple JOINs // bug 4429: sqlite doesnt like the parentheses if ($addme && $dbconn->databaseType != 'sqlite') { $from = '(' . $from . ')'; } // Add the LEFT JOIN ... ON ... parts from hitcount $from .= ' LEFT JOIN ' . $hitcountdef['table']; $from .= ' ON ' . $hitcountdef['field'] . ' = ' . $publicationsdef['id']; $addme = 1; } if (!empty($required['rating']) && isset($ratingsdef)) { // add this for SQL compliance when there are multiple JOINs // bug 4429: sqlite doesnt like the parentheses if ($addme && $dbconn->databaseType != 'sqlite') { $from = '(' . $from . ')'; } // Add the LEFT JOIN ... ON ... parts from ratings $from .= ' LEFT JOIN ' . $ratingsdef['table']; $from .= ' ON ' . $ratingsdef['field'] . ' = ' . $publicationsdef['id']; $addme = 1; } if (count($cids) > 0) { // add this for SQL compliance when there are multiple JOINs // bug 4429: sqlite doesnt like the parentheses if ($addme && $dbconn->databaseType != 'sqlite') { $from = '(' . $from . ')'; } // Add the LEFT JOIN ... ON ... parts from categories $from .= ' LEFT JOIN ' . $categoriesdef['table']; $from .= ' ON ' . $categoriesdef['field'] . ' = ' . $publicationsdef['id']; if (!empty($categoriesdef['more']) && $dbconn->databaseType != 'sqlite') { $from = '(' . $from . ')'; $from .= $categoriesdef['more']; } } $query .= ' FROM ' . $from; // TODO: check the order of the conditions for brain-dead databases ? // Create the WHERE part $where = array(); // we rely on leftjoin() to create the necessary publications clauses now if (!empty($publicationsdef['where'])) { $where[] = $publicationsdef['where']; } if (!empty($required['counter']) && !empty($hitcountdef['where'])) { $where[] = $hitcountdef['where']; } if (!empty($required['rating']) && !empty($ratingsdef['where'])) { $where[] = $ratingsdef['where']; } if (count($cids) > 0) { // we rely on leftjoin() to create the necessary categories clauses $where[] = $categoriesdef['where']; } if (count($where) > 0) { $query .= ' WHERE ' . join(' AND ', $where); } // TODO: support other non-publications fields too someday ? // Create the ORDER BY part if (count($sortlist) > 0) { $sortparts = array(); $seenid = 0; foreach ($sortlist as $criteria) { // ignore empty sort criteria if (empty($criteria)) { continue; } // split off trailing ASC or DESC if (preg_match('/^(.+)\\s+(ASC|DESC)\\s*$/i', $criteria, $matches)) { $criteria = trim($matches[1]); $sortorder = strtoupper($matches[2]); } else { $sortorder = ''; } if ($criteria == 'title') { $sortparts[] = $publicationsdef['title'] . ' ' . (!empty($sortorder) ? $sortorder : 'ASC'); // } elseif ($criteria == 'create_date' || $criteria == 'date') { // $sortparts[] = $publicationsdef['create_date'] . ' ' . (!empty($sortorder) ? $sortorder : 'DESC'); } elseif ($criteria == 'hits' && !empty($hitcountdef['hits'])) { $sortparts[] = $hitcountdef['hits'] . ' ' . (!empty($sortorder) ? $sortorder : 'DESC'); } elseif ($criteria == 'rating' && !empty($ratingsdef['rating'])) { $sortparts[] = $ratingsdef['rating'] . ' ' . (!empty($sortorder) ? $sortorder : 'DESC'); } elseif ($criteria == 'owner' && !empty($usersdef['name'])) { $sortparts[] = $usersdef['name'] . ' ' . (!empty($sortorder) ? $sortorder : 'ASC'); } elseif ($criteria == 'relevance' && !empty($publicationsdef['relevance'])) { $sortparts[] = 'relevance' . ' ' . (!empty($sortorder) ? $sortorder : 'DESC'); } elseif ($criteria == 'id') { $sortparts[] = $publicationsdef['id'] . ' ' . (!empty($sortorder) ? $sortorder : 'ASC'); $seenid = 1; // other publications fields, e.g. summary, notes, ... } elseif (!empty($publicationsdef[$criteria])) { $sortparts[] = $publicationsdef[$criteria] . ' ' . (!empty($sortorder) ? $sortorder : 'ASC'); } else { // ignore unknown sort fields } } // add sorting by id for unique sort order if (count($sortparts) < 2 && empty($seenid)) { $sortparts[] = $publicationsdef['id'] . ' DESC'; } $query .= ' ORDER BY ' . join(', ', $sortparts); } elseif (!empty($search) && !empty($searchtype) && substr($searchtype, 0, 8) == 'fulltext') { // For fulltext, let the database return the publications by relevance here (= default) // For fulltext in boolean mode, add MATCH () ... AS relevance ... ORDER BY relevance DESC (cfr. leftjoin) if (!empty($required['relevance']) && $searchtype == 'fulltext boolean') { $query .= ' ORDER BY relevance DESC, ' . $publicationsdef['create_date'] . ' DESC, ' . $publicationsdef['id'] . ' DESC'; } } else { // default is 'create_date' $query .= ' ORDER BY ' . $publicationsdef['create_date'] . ' DESC, ' . $publicationsdef['id'] . ' DESC'; } //echo $query; // Run the query - finally :-) if (isset($numitems) && is_numeric($numitems)) { $result =& $dbconn->SelectLimit($query, $numitems, $startnum - 1); } else { $result =& $dbconn->Execute($query); } if (!$result) { return; } $itemids_per_type = array(); // Put publications into result array for (; !$result->EOF; $result->MoveNext()) { $data = $result->fields; $item = array(); // loop over all required fields again foreach ($required as $field => $val) { if ($field == 'cids' || $field == 'dynamicdata' || $val != 1) { continue; } $value = array_shift($data); if ($field == 'rating') { $value = intval($value); } $item[$field] = $value; } // check security - don't generate an exception here if (empty($required['cids']) && !xarSecurityCheck('ViewPublications', 0, 'Publication', "{$item['pubtype_id']}:All:{$item['owner']}:{$item['id']}")) { continue; } $publications[] = $item; if (!empty($required['dynamicdata'])) { $pubtype = $item['pubtype_id']; if (!isset($itemids_per_type[$pubtype])) { $itemids_per_type[$pubtype] = array(); } $itemids_per_type[$pubtype][] = $item['id']; } } $result->Close(); if (!empty($required['cids']) && count($publications) > 0) { // Get all the categories at once $ids = array(); foreach ($publications as $article) { $ids[] = $article['id']; } // Load API if (!xarModAPILoad('categories', 'user')) { return; } // Get the links for the Array of iids we have $cids = xarModAPIFunc('categories', 'user', 'getlinks', array('iids' => $ids, 'reverse' => 1, 'modid' => $regid)); // Inserting the corresponding Category ID in the Publication Description $delete = array(); $cachesec = array(); foreach ($publications as $key => $article) { if (isset($cids[$article['id']]) && count($cids[$article['id']]) > 0) { $publications[$key]['cids'] = $cids[$article['id']]; foreach ($cids[$article['id']] as $cid) { if (!xarSecurityCheck('ViewPublications', 0, 'Publication', "{$article['pubtype_id']}:{$cid}:{$article['owner']}:{$article['id']}")) { $delete[$key] = 1; break; } if (!isset($cachesec[$cid])) { // TODO: combine with ViewCategoryLink check when we can combine module-specific // security checks with "parent" security checks transparently ? $cachesec[$cid] = xarSecurityCheck('ReadCategories', 0, 'Category', "All:{$cid}"); } if (!$cachesec[$cid]) { $delete[$key] = 1; break; } } } else { if (!xarSecurityCheck('ViewPublications', 0, 'Publication', "{$article['pubtype_id']}:All:{$article['owner']}:{$article['id']}")) { $delete[$key] = 1; continue; } } } if (count($delete) > 0) { foreach ($delete as $key => $val) { unset($publications[$key]); } } } if (!empty($required['dynamicdata']) && count($publications) > 0) { foreach ($itemids_per_type as $pubtype => $itemids) { if (!xarModIsHooked('dynamicdata', 'publications', $pubtype)) { continue; } list($properties, $items) = xarModAPIFunc('dynamicdata', 'user', 'getitemsforview', array('module' => 'publications', 'itemtype' => $pubtype, 'itemids' => $itemids, 'state' => 1)); if (empty($properties) || count($properties) == 0) { continue; } foreach ($publications as $key => $article) { // otherwise publications (of different pub types) with dd properties having the same // names reset previously set values to empty string for each iteration based on the pubtype if ($article['pubtype_id'] != $pubtype) { continue; } foreach (array_keys($properties) as $name) { if (isset($items[$article['id']]) && isset($items[$article['id']][$name])) { $value = $items[$article['id']][$name]; } else { $value = $properties[$name]->default; } $publications[$key][$name] = $value; // TODO: clean up this temporary fix if (!empty($value)) { $publications[$key][$name . '_output'] = $properties[$name]->showOutput(array('value' => $value)); } } } } } return $publications; }