function publications_userapi_pageintrees($args) { extract($args); if (!isset($pid) || !is_numeric($pid) || !isset($tree_roots) || !is_array($tree_roots)) { return false; } $xartable = xarDB::getTables(); $dbconn = xarDB::getConn(); // For the page to be somewhere in a tree, identified by the root of that tree, // it's xar_left column must be between the xar_left and xar_right columns // of the tree root. $query = 'SELECT COUNT(*)' . ' FROM ' . $xartable['publications'] . ' AS testpage' . ' INNER JOIN ' . $xartable['publications'] . ' AS testtrees' . ' ON testpage.leftpage_id BETWEEN testtrees.leftpage_id AND testtrees.rightpage_id' . ' AND testtrees.id IN (?' . str_repeat(',?', count($tree_roots) - 1) . ')' . ' WHERE testpage.id = ?'; // Add the pid onto the tree roots to form the full bind variable set. $tree_roots[] = $pid; $result = $dbconn->execute($query, $tree_roots); if (!$result || $result->EOF) { return false; } list($count) = $result->fields; if ($count > 0) { return true; } else { return false; } }
/** * Publications Module * * @package modules * @subpackage publications module * @category Third Party Xaraya Module * @version 2.0.0 * @copyright (C) 2011 Netspan AG * @license GPL {@link http://www.gnu.org/licenses/gpl.html} * @author Marc Lutolf <*****@*****.**> */ function publications_adminapi_delete($args) { // Get arguments from argument array extract($args); // Argument check if (!isset($itemid)) { $msg = xarML('Invalid #(1) for #(2) function #(3)() in module #(4)', 'publication ID', 'admin', 'delete', 'Publications'); throw new BadParameterException(null, $msg); } $ids = !is_array($itemid) ? explode(',', $itemid) : $itemid; if (!isset($deletetype)) { $deletetype = 0; } sys::import('xaraya.structures.query'); $table = xarDB::getTables(); switch ($deletetype) { case 0: default: $q = new Query('UPDATE', $table['publications']); $q->addfield('state', 0); break; case 10: $q = new Query('DELETE', $table['publications']); break; } $q->in('id', $ids); if (!$q->run()) { return false; } return true; }
/** * utility function to pass individual item links to a caller * * @param $args['itemids'] array of item ids to get * @return array Array containing the itemlink(s) for the item(s). */ function publications_userapi_getitemlinks($args) { $itemlinks = array(); sys::import('xaraya.structures.query'); $xartable = xarDB::getTables(); $q = new Query('SELECT', $xartable['publications']); $q->addfield('id'); $q->addfield('title'); $q->addfield('description'); $q->addfield('pubtype_id'); $q->in('state', array(3, 4)); if (!empty($args['itemids'])) { $itemids = explode(',', $args['itemids']); $q->in('id', $itemids); } $q->addorder('title'); $q->run(); $result = $q->output(); if (empty($result)) { return $itemlinks; } foreach ($result as $item) { if (empty($item['title'])) { $item['title'] = xarML('Display Publication'); } $itemlinks[$item['id']] = array('url' => xarModURL('publications', 'user', 'display', array('id' => $item['id'])), 'title' => $item['title'], 'label' => $item['description']); } return $itemlinks; }
/** * get next article * Note : the following parameters are all optional (except id and ptid) * * @param $args['id'] the article ID we want to have the next article of * @param $args['ptid'] publication type ID (for news, sections, reviews, ...) * @param $args['sort'] sort order ('date','title','hits','rating',...) * @param $args['owner'] the ID of the author * @param $args['state'] array of requested status(es) for the publications * @param $args['enddate'] publications published before enddate * (unix timestamp format) * @return array of article fields, or false on failure */ function publications_userapi_getnext($args) { // Get arguments from argument array extract($args); // Optional argument if (empty($sort)) { $sort = 'date'; } if (!isset($state)) { // frontpage or approved $state = array(PUBLICATIONS_STATE_FRONTPAGE, PUBLICATIONS_STATE_APPROVED); } // Default fields in publications (for now) $fields = array('id', 'title'); // Security check if (!xarSecurityCheck('ViewPublications')) { return; } // 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); // Create the query $query = "SELECT {$publicationsdef['id']}, {$publicationsdef['title']}, {$publicationsdef['pubtype_id']}, {$publicationsdef['owner']}\n FROM {$publicationsdef['table']} WHERE "; // we rely on leftjoin() to create the necessary publications clauses now if (!empty($publicationsdef['where'])) { $query .= " {$publicationsdef['where']} AND "; } // Get current article $current = xarModAPIFunc('publications', 'user', 'get', array('id' => $id)); // Create the ORDER BY part switch ($sort) { case 'title': $query .= $publicationsdef['title'] . ' > ' . $dbconn->qstr($current['title']) . ' ORDER BY ' . $publicationsdef['title'] . ' ASC, ' . $publicationsdef['id'] . ' ASC'; break; case 'id': $query .= $publicationsdef['id'] . ' > ' . $current['id'] . ' ORDER BY ' . $publicationsdef['id'] . ' ASC'; break; case 'data': default: $query .= $publicationsdef['pubdate'] . ' > ' . $dbconn->qstr($current['pubdate']) . ' ORDER BY ' . $publicationsdef['pubdate'] . ' ASC, ' . $publicationsdef['id'] . ' ASC'; } // Run the query - finally :-) $result =& $dbconn->SelectLimit($query, 1, 0); if (!$result) { return; } $item = array(); list($item['id'], $item['title'], $item['pubtype_id'], $item['owner']) = $result->fields; $result->Close(); // TODO: grab categories & check against them too // check security - don't generate an exception here if (!xarSecurityCheck('ViewPublications', 0, 'Publication', "{$item['pubtype_id']}:All:{$item['owner']}:{$item['id']}")) { return array(); } return $item; }
/** * @returns int (calendar id on success, false on failure) */ function calendar_adminapi_create_calendars($args) { extract($args); // argument check if (!isset($calname)) { $msg = xarML('Calendar name not specified', 'admin', 'create', 'calendar'); throw new Exception($msg); } // TODO: should I move these two issets to the admin function // admin/create_calendars.php? --amoro if (!isset($mod_id)) { $module = xarController::$request->getInfo(); $mod_id = xarMod::getRegID($module[0]); } if (!isset($role_id)) { $role_id = xarSession::getVar('role_id'); } // Load up database details. $dbconn = xarDB::getConn(); $xartable = xarDB::getTables(); $caltable = $xartable['calendars']; // Insert instance details. $nextId = $dbconn->GenId($caltable); $query = 'INSERT INTO ' . $caltable . ' ( xar_id, xar_role_id, xar_mod_id, xar_name ) VALUES (?, ?, ?, ?)'; $result =& $dbconn->Execute($query, array($nextId, $role_id, $mod_id, $calname)); if (!$result) { return; } // Get ID of row inserted. $calendid = $dbconn->PO_Insert_ID($caltable, 'xar_id'); // If not database type also add file info // Allow duplicate files here, to make it easier to delete them // WARNING: if somebody changes this you should also change the // delete function to avoid major dataloss!!! --amoro if ($addtype != 'db') { $filestable = $xartable['calfiles']; $cal_filestable = $xartable['calendars_files']; $nextID = $dbconn->GenId($filestable); $query = 'INSERT INTO ' . $filestable . ' ( xar_id, xar_path ) VALUES (?, ?)'; $result =& $dbconn->Execute($query, array($nextID, $fileuri)); // Get ID of row inserted. $fileid = $dbconn->PO_Insert_ID($filestable, 'xar_id'); $query = 'INSERT INTO ' . $cal_filestable . ' ( xar_calendars_id, xar_files_id ) VALUES (?, ?)'; $result =& $dbconn->Execute($query, array($calendid, $fileid)); } return $calendid; }
/** * 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; }
function calendar_userapi_getevents($args) { extract($args); $xartable = xarDB::getTables(); $q = new Query('SELECT'); $q->addtable($xartable['calendar_event']); $q->ge('start_time', $day->thisDay(TRUE)); $q->lt('start_time', $day->nextDay(TRUE)); if (!$q->run()) { return; } return $q->output(); }
/** * count the number of items per month * @param $args['cids'] not supported here (yet ?) * @param $args['ptid'] publication type ID we're interested in * @param $args['state'] array of requested status(es) for the publications * @return array array(month => count), or false on failure */ function publications_userapi_getmonthcount($args) { // Get database setup $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); // Bug 1590 - Create custom query supported by each database. $dbtype = xarDB::getType(); switch ($dbtype) { case 'mysql': $query = "SELECT LEFT(FROM_UNIXTIME(start_date),7) AS mymonth, COUNT(*) FROM " . $publicationsdef['table']; // echo $query;exit; break; case 'postgres': $query = "SELECT TO_CHAR(ABSTIME(pubdate),'YYYY-MM') AS mymonth, COUNT(*) FROM " . $publicationsdef['table']; break; case 'mssql': $query = "SELECT LEFT(CONVERT(VARCHAR,DATEADD(ss,pubdate,'1/1/1970'),120),7) as mymonth, COUNT(*) FROM " . $publicationsdef['table']; break; // TODO: Add SQL queries for Oracle, etc. // TODO: Add SQL queries for Oracle, etc. default: return; } if (!empty($publicationsdef['where'])) { $query .= ' WHERE ' . $publicationsdef['where']; } switch ($dbtype) { case 'mssql': $query .= " GROUP BY LEFT(CONVERT(VARCHAR,DATEADD(ss,pubdate,'1/1/1970'),120),7)"; break; default: $query .= ' GROUP BY mymonth'; break; } $result =& $dbconn->Execute($query); if (!$result) { return; } $months = array(); while (!$result->EOF) { list($month, $count) = $result->fields; $months[$month] = $count; $result->MoveNext(); } return $months; }
/** * 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; }
/** * Given an itemid, get the publication type * CHECKME: use get in place of this function? */ function publications_userapi_getitempubtype($args) { if (empty($args['itemid'])) { throw new MissingParameterException('itemid'); } sys::import('xaraya.structures.query'); $xartables = xarDB::getTables(); $q = new Query('SELECT', $xartables['publications']); $q->addfield('pubtype_id'); $q->eq('id', $args['itemid']); if (!$q->run()) { return; } $result = $q->row(); if (empty($result)) { return 0; } return $result['pubtype_id']; }
/** * Given an itemid, get the publication type * CHECKME: use get in place of this function? */ function publications_userapi_getpubtypeaccess($args) { if (empty($args['name'])) { throw new MissingParameterException('name'); } sys::import('xaraya.structures.query'); $xartables = xarDB::getTables(); $q = new Query('SELECT', $xartables['publications_types']); $q->addfield('access'); $q->eq('name', $args['name']); if (!$q->run()) { return; } $result = $q->row(); if (empty($result)) { return "a:0:{}"; } return $result['access']; }
/** * get the number of publications per publication type * @param $args['state'] array of requested status(es) for the publications * @return array array(id => count), or false on failure */ function publications_userapi_getpubcount($args) { if (!empty($args['state'])) { $statestring = 'all'; } else { if (is_array($args['state'])) { sort($args['state']); $statestring = join('+', $args['state']); } else { $statestring = $args['state']; } } if (xarVarIsCached('Publications.PubCount', $statestring)) { return xarVarGetCached('Publications.PubCount', $statestring); } $pubcount = array(); $dbconn = xarDB::getConn(); $tables = xarDB::getTables(); sys::import('xaraya.structures.query'); $q = new Query('SELECT', $tables['publications']); $q->addfield('pubtype_id'); $q->addfield('COUNT(state) AS count'); $q->addgroup('pubtype_id'); if (!empty($args['state'])) { } else { if (is_array($args['state'])) { $q->in('state', $args['state']); } else { $q->eq('state', $args['state']); } } // $q->qecho(); if (!$q->run()) { return; } $pubcount = array(); foreach ($q->output() as $key => $value) { $pubcount[$value['pubtype_id']] = $value['count']; } xarVarSetCached('Publications.PubCount', $statestring, $pubcount); return $pubcount; }
function publications_treeapi_getleftright($args) { // Expand the arguments. extract($args); // Database. $dbconn = xarDB::getConn(); if ($id != 0) { // Insert point is a real item. $query = 'SELECT xar_parent, xar_left, xar_right' . ' FROM ' . $tablename . ' WHERE ' . $idname . ' = ?'; $result = $dbconn->execute($query, array((int) $id)); if (!$result->EOF) { list($parent, $left, $right) = $result->fields; $return = array('parent' => (int) $parent, 'left' => (int) $left, 'right' => (int) $right); } else { // Item not found. // TODO: raise error. return; } } else { // Insert point is the virtual root. // This query should return EOF when the table is empty, // but it doesn't (on MySQL, at least - I'm sure a MAX() of // no rows returns no rows in Oracle). $query = 'SELECT 0, MIN(xar_left)-1 as xar_left, MAX(xar_right)+1 as xar_right' . ' FROM ' . $tablename; $result = $dbconn->execute($query); $parent = 0; if (!$result->EOF) { list($parent, $left, $right) = $result->fields; $return = array('parent' => (int) $parent, 'left' => (int) $left, 'right' => (int) $right); // Hack for MySQL where EOF does not work on MIN/MAX group functions. if (!isset($left)) { $return = array('parent' => 0, 'left' => 1, 'right' => 2); } } else { $return = array('parent' => 0, 'left' => 1, 'right' => 2); } } return $return; }
/** * Publications Module * * @package modules * @subpackage publications module * @category Third Party Xaraya Module * @version 2.0.0 * @copyright (C) 2011 Netspan AG * @license GPL {@link http://www.gnu.org/licenses/gpl.html} * @author Marc Lutolf <*****@*****.**> */ function publications_userapi_gettranslationid($args) { if (!isset($args['id'])) { throw new BadParameterException('id'); } if (empty($args['id'])) { return 0; } // We can check on a full locale or just a partial one (excluding charset) if (empty($args['partiallocale'])) { $args['partiallocale'] = 0; } // We can look for a specific translation if (empty($args['locale'])) { $locale = xarUserGetNavigationLocale(); } else { $locale = $args['locale']; } sys::import('xaraya.structures.query'); if ($args['partiallocale']) { $parts = explode('.', $locale); $locale = $parts[0]; } $xartable = xarDB::getTables(); if (empty($args['locale'])) { // Return the id of the translation if it exists, or else the base document $q = new Query('SELECT', $xartable['publications']); $q->addfield('id'); $q->eq('locale', $locale); $c[] = $q->peq('id', $args['id']); $c[] = $q->peq('parent_id', $args['id']); $q->qor($c); if (!$q->run()) { return $args['id']; } $result = $q->row(); if (empty($result)) { return $args['id']; } return $result['id']; } elseif ($args['locale'] == xarUserGetNavigationLocale()) { // No need to look further return $args['id']; } elseif ($args['locale'] == xarModVars::get('publications', 'defaultlanguage')) { // Force getting the base document $q = new Query('SELECT', $xartable['publications']); $q->addfield('parent_id'); $q->eq('id', $args['id']); if (!$q->run()) { return $args['id']; } $result = $q->row(); if (empty($result)) { return $args['id']; } // If this was already the base document, return its ID if (empty($result['parent_id'])) { return $args['id']; } // Else return the parent ID return $result['parent_id']; } else { // Force getting another translation $q = new Query('SELECT'); $q->addtable($xartable['publications'], 'p1'); $q->addtable($xartable['publications'], 'p2'); $q->join('p2.parent_id', 'p1.parent_id'); $q->addfield('p2.id'); $q->eq('p2.locale', $locale); $q->eq('p1.id', $args['id']); if (!$q->run()) { return $args['id']; } $result = $q->row(); if (empty($result)) { return $args['id']; } return $result['id']; } if (xarUserGetVar('uname') == 'random') { $xartable = xarDB::getTables(); $q = new Query('SELECT'); $q->addtable($xartable['publications'], 'p1'); $q->addtable($xartable['publications'], 'p2'); $q->join('p2.id', 'p1.parent_id'); $q->addfield('p1.id'); $c[] = $q->peq('p1.id', $args['id']); $c[] = $q->peq('p1.parent_id', $args['id']); $c[] = $q->peq('p2.id', $args['id']); $q->qor($c); $d[] = $q->peq('p1.locale', $args['locale']); $d[] = $q->peq('p2.locale', $args['locale']); $q->qor($d); if (!$q->run()) { return $args['id']; } $q->qecho(); $result = $q->row(); if (empty($result)) { return $args['id']; } return $result['id']; } }
/** * Get pages relative to a given page * * Filters: * Add an arg of the type $args['filter_foo'] = bar * will add a condition to the SELECT as * WHERE foo = bar * */ function publications_userapi_get_sitemap_pages($args) { if (empty($args['itemid'])) { $args['itemid'] = 0; } if (empty($args['scope'])) { $args['scope'] = 'descendants'; } if ($args['itemid'] == 0 && $args['scope'] == 'descendants') { $args['scope'] = 'all'; } if (empty($args['sort'])) { $args['sort'] = 0; } // Make sure we have the base translation id if (!empty($args['itemid'])) { $args['itemid'] = xarMod::apiFunc('publications', 'user', 'gettranslationid', array('id' => $args['itemid'], 'locale' => xarModVars::get('publications', 'defaultlanguage'))); } // Identify any filters $filters = array(); foreach ($args as $k => $v) { if (strpos($k, 'filter_') === 0) { $argname = substr($k, 7); $filters[$argname] = $v; } } $xartable = xarDB::getTables(); sys::import('xaraya.structures.query'); $q = new Query(); $q->addtable($xartable['publications'], 'p'); switch ($args['scope']) { case 'all': $q->gt('p.leftpage_id', 0); break; case 'descendants': $q->addtable($xartable['publications'], 'root'); $q->eq('root.id', $args['itemid']); $q->le('root.leftpage_id', 'expr:p.leftpage_id'); $q->ge('root.rightpage_id', 'expr:p.rightpage_id'); break; case 'children': $q->eq('p.parentpage_id', $args['itemid']); break; case 'siblings': $q->addtable($xartable['publications'], 'p1'); $q->join('p.parentpage_id', 'p1.parentpage_id'); $q->eq('p1.id', $args['itemid']); break; } if (!empty($args['itemtype'])) { $q->eq('p.pubtype_id', $args['itemtype']); } $q->eq('p.sitemap_flag', 1); $q->gt('p.state', 2); $q->addfield('p.id AS id'); $q->addfield('p.name AS name'); $q->addfield('p.title AS title'); $q->addfield('p.description AS description'); $q->addfield('p.sitemap_source_flag AS sitemap_source_flag'); $q->addfield('p.sitemap_alias AS sitemap_alias'); $q->addfield('p.pubtype_id AS pubtype_id'); $q->addfield('p.rightpage_id AS rightpage_id'); // Add any fiters we found foreach ($filters as $k => $v) { $q->eq('p.' . $k, $v); } // We can force alpha sorting, or else sort according to tree position if ($args['sort']) { $q->setorder('p.title'); } else { $q->setorder('p.leftpage_id'); } // $q->qecho(); $q->run(); $pages = $q->output(); $depthstack = array(); foreach ($pages as $key => $page) { // Calculate the relative nesting level. // 'depth' is 0-based. Top level (root node) is zero. if (!empty($depthstack)) { while (!empty($depthstack) && end($depthstack) < $page['rightpage_id']) { array_pop($depthstack); } } $depthstack[$page['id']] = $page['rightpage_id']; $pages[$key]['depth'] = empty($depthstack) ? 0 : count($depthstack) - 1; // This item is the path for each page, based on page IDs. // It is effectively a list of ancestor IDs for a page. // FIXME: some paths seem to get a '0' root ID. They should only have real page IDs. $pages[$key]['idpath'] = array_keys($depthstack); $pathstack[$key] = $page['name']; // This item is the path for each page, based on names. // Imploding it can give a directory-style path, which is handy // in admin pages and reports. $pages[$key]['namepath'] = $pathstack; } // If we are looking for translations rather than base documents, then find what translations are available and substitute them // CHECKME: is there a better way? // If there is no translation the base document remains. Is this desired outcome? if (!empty($pages) && xarModVars::get('publications', 'defaultlanguage') != xarUserGetNavigationLocale()) { $indexedpages = array(); foreach ($pages as $v) { $indexedpages[$v['id']] = $v; } $ids = array_keys($indexedpages); $q = new Query(); $q->addtable($xartable['publications']); $q->addfield('id'); $q->addfield('parent_id'); $q->addfield('name'); $q->addfield('title'); $q->addfield('description'); $q->addfield('sitemap_source_flag'); $q->addfield('sitemap_alias'); $q->addfield('pubtype_id'); $q->in('parent_id', $ids); $q->eq('locale', xarUserGetNavigationLocale()); // Add any fiters we found foreach ($filters as $k => $v) { $q->eq($k, $v); } $q->run(); foreach ($q->output() as $row) { // Copy the name and id paths so we don't have to recalculate them $row['depth'] = $indexedpages[$row['parent_id']]['depth']; $row['idpath'] = $indexedpages[$row['parent_id']]['idpath']; $row['namepath'] = $indexedpages[$row['parent_id']]['namepath']; // Add the entire row to the result pages $indexedpages[$row['parent_id']] = $row; } $pages =& $indexedpages; } return $pages; }
/** * count number of items depending on additional module criteria * * @param array group * @return array number of items with descriptors */ function publications_adminapi_getstats($args) { extract($args); $allowedfields = array('pubtype_id', 'state', 'owner', 'locale', 'pubdate_year', 'pubdate_month', 'pubdate_day'); if (empty($group)) { $group = array(); } $newfields = array(); $newgroups = array(); foreach ($group as $field) { if (empty($field) || !in_array($field, $allowedfields)) { continue; } if ($field == 'pubdate_year') { $dbtype = xarDB::getType(); switch ($dbtype) { case 'mysql': $newfields[] = "LEFT(FROM_UNIXTIME(start_date),4) AS myyear"; $newgroups[] = "myyear"; break; case 'postgres': $newfields[] = "TO_CHAR(ABSTIME(start_date),'YYYY') AS myyear"; // CHECKME: do we need to use TO_CHAR(...) for the group field too ? $newgroups[] = "myyear"; break; case 'mssql': $newfields[] = "LEFT(CONVERT(VARCHAR,DATEADD(ss,start_date,'1/1/1970'),120),4) as myyear"; $newgroups[] = "LEFT(CONVERT(VARCHAR,DATEADD(ss,start_date,'1/1/1970'),120),4)"; break; // TODO: Add SQL queries for Oracle, etc. // TODO: Add SQL queries for Oracle, etc. default: continue; } } elseif ($field == 'pubdate_month') { $dbtype = xarDB::getType(); switch ($dbtype) { case 'mysql': $newfields[] = "LEFT(FROM_UNIXTIME(start_date),7) AS mymonth"; $newgroups[] = "mymonth"; break; case 'postgres': $newfields[] = "TO_CHAR(ABSTIME(start_date),'YYYY-MM') AS mymonth"; // CHECKME: do we need to use TO_CHAR(...) for the group field too ? $newgroups[] = "mymonth"; break; case 'mssql': $newfields[] = "LEFT(CONVERT(VARCHAR,DATEADD(ss,start_date,'1/1/1970'),120),7) as mymonth"; $newgroups[] = "LEFT(CONVERT(VARCHAR,DATEADD(ss,start_date,'1/1/1970'),120),7)"; break; // TODO: Add SQL queries for Oracle, etc. // TODO: Add SQL queries for Oracle, etc. default: continue; } } elseif ($field == 'pubdate_day') { $dbtype = xarDB::getType(); switch ($dbtype) { case 'mysql': $newfields[] = "LEFT(FROM_UNIXTIME(start_date),10) AS myday"; $newgroups[] = "myday"; break; case 'postgres': $newfields[] = "TO_CHAR(ABSTIME(start_date),'YYYY-MM-DD') AS myday"; // CHECKME: do we need to use TO_CHAR(...) for the group field too ? $newgroups[] = "myday"; break; case 'mssql': $newfields[] = "LEFT(CONVERT(VARCHAR,DATEADD(ss,start_date,'1/1/1970'),120),10) as myday"; $newgroups[] = "LEFT(CONVERT(VARCHAR,DATEADD(ss,start_date,'1/1/1970'),120),10)"; break; // TODO: Add SQL queries for Oracle, etc. // TODO: Add SQL queries for Oracle, etc. default: continue; } } else { $newfields[] = $field; $newgroups[] = $field; } } if (empty($newfields) || count($newfields) < 1) { $newfields = array('pubtype_id', 'state', 'owner'); $newgroups = array('pubtype_id', 'state', 'owner'); } // Database information $dbconn = xarDB::getConn(); $xartables = xarDB::getTables(); $query = 'SELECT ' . join(', ', $newfields) . ', COUNT(*) FROM ' . $xartables['publications'] . ' GROUP BY ' . join(', ', $newgroups) . ' ORDER BY ' . join(', ', $newgroups); $result =& $dbconn->Execute($query); if (!$result) { return; } $stats = array(); while (!$result->EOF) { if (count($newfields) > 3) { list($field1, $field2, $field3, $field4, $count) = $result->fields; $stats[$field1][$field2][$field3][$field4] = $count; } elseif (count($newfields) == 3) { list($field1, $field2, $field3, $count) = $result->fields; $stats[$field1][$field2][$field3] = $count; } elseif (count($newfields) == 2) { list($field1, $field2, $count) = $result->fields; $stats[$field1][$field2] = $count; } elseif (count($newfields) == 1) { list($field1, $count) = $result->fields; $stats[$field1] = $count; } $result->MoveNext(); } $result->Close(); return $stats; }
public function encode(xarRequest $request) { if ($request->getType() == 'admin') { return parent::encode($request); } $params = $request->getFunctionArgs(); $path = array(); switch ($request->getFunction()) { case 'search': $path[] = 'search'; $path = array_merge($path, $params); break; case 'view': $path[] = 'view'; if (isset($params['ptid'])) { if (xarModVars::get('publications', 'usetitleforurl')) { // Get all publication types present if (empty($this->pubtypes)) { $this->pubtypes = xarModAPIFunc('publications', 'user', 'get_pubtypes'); } // Match to the function token foreach ($this->pubtypes as $id => $pubtype) { if ($params['ptid'] == $id) { $path[] = strtolower($pubtype['description']); break; } } } else { $path[] = $params['ptid']; } } unset($params['ptid']); break; case 'viewmap': $path[] = 'viewmap'; $params = array(); break; case 'display': if (isset($params['itemid'])) { sys::import('xaraya.structures.query'); xarModLoad('publications'); $xartables = xarDB::getTables(); $q = new Query('SELECT', $xartables['publications']); $q->eq('id', $params['itemid']); $q->addfield('pubtype_id'); $q->addfield('name'); $q->addfield('id'); $q->run(); $result = $q->row(); if (xarModVars::get('publications', 'usetitleforurl')) { // Get all publication types present if (empty($this->pubtypes)) { $this->pubtypes = xarModAPIFunc('publications', 'user', 'get_pubtypes'); } if (!empty($result['pubtype_id'])) { $path[] = strtolower($this->pubtypes[$result['pubtype_id']]['description']); } if (!empty($result['name'])) { $path[] = strtolower($result['name']); } } else { if (!empty($result['id'])) { $path[] = $result['id']; } } } $params = array(); break; case 'main': // We need a page ID to continue, for now. // TODO: allow this to be expanded to page names. if (empty($params['pid'])) { return; } static $pages = NULL; // The components of the path. // $get = $args; // Get the page tree that includes this page. // TODO: Do some kind of cacheing on a tree-by-tree basis to prevent // fetching this too many times. Every time any tree is fetched, anywhere // in this module, it should be added to the cache so it can be used again. // For now we are going to fetch all pages, without DD, to cut down on // the number of queries, although we are making an assumption that the // number of pages is not going to get too high. if (empty($pages)) { // Fetch all pages, with no DD required. $pages = xarMod::apiFunc('publications', 'user', 'getpages', array('dd_flag' => false, 'key' => 'pid')); } // Check that the pid is a valid page. if (!isset($pages[$params['pid']])) { return; } $use_shortest_paths = xarModVars::get('publications', 'shortestpath'); // Consume the pid from the get parameters. $pid = $params['pid']; unset($params['pid']); // 'Consume' the function now we know we have enough information. // unset($params['func']); // Follow the tree up to the root. $pid_follow = $pid; while ($pages[$pid_follow]['parent_key'] != 0) { // TODO: could do with an API to get all aliases for a given module in one go. if (!empty($use_shortest_paths) && xarModGetAlias($pages[$pid_follow]['name']) == 'publications') { break; } array_unshift($path, $pages[$pid_follow]['name']); $pid_follow = $pages[$pid_follow]['parent_key']; } // Do the final path part. array_unshift($path, $pages[$pid_follow]['name']); // If the base path component is not the module alias, then add the // module name to the start of the path. if (xarModGetAlias($pages[$pid_follow]['name']) != 'publications') { // array_unshift($path, 'publications'); } // Now we have the basic path, we can check if there are any custom // URL handlers to handle the remainder of the GET parameters. // The handler is placed into the xarencodeapi API directory, and will // return two arrays: 'path' with path components and 'get' with // any unconsumed (or new) get parameters. if (!empty($pages[$pid]['encode_url'])) { $extra = xarMod::apiFunc('publications', 'encode', $pages[$pid]['encode_url'], $get, false); if (!empty($extra)) { // The handler has supplied some further short URL path components. if (!empty($extra['path'])) { $path = array_merge($path, $extra['path']); } // Assume it has consumed some GET parameters too. // Take what is left (i.e. unconsumed). if (isset($extra['get']) && is_array($extra['get'])) { $get = $extra['get']; } } } break; default: return; break; } // Encode the processed params $request->setFunction($this->getFunction($path)); // Send the unprocessed params back $request->setFunctionArgs($params); return parent::encode($request); }
/** * 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; }
function publications_admin_updateconfig() { // Confirm authorisation code if (!xarSecConfirmAuthKey()) { return; } // Get parameters //A lot of these probably are bools, still might there be a need to change the template to return //'true' and 'false' to use those... if (!xarVarFetch('settings', 'array', $settings, array(), XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('usetitleforurl', 'int', $usetitleforurl, xarModVars::get('publications', 'usetitleforurl'), XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('defaultstate', 'isset', $defaultstate, 0, XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('defaultsort', 'isset', $defaultsort, 'date', XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('usealias', 'int', $usealias, 0, XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('ptid', 'isset', $ptid, xarModVars::get('publications', 'defaultpubtype'), XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('multilanguage', 'int', $multilanguage, 0, XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('tab', 'str:1:10', $data['tab'], 'global', XARVAR_NOT_REQUIRED)) { return; } if (!xarSecurityCheck('AdminPublications', 1, 'Publication', "{$ptid}:All:All:All")) { return; } if ($data['tab'] == 'global') { if (!xarVarFetch('defaultpubtype', 'isset', $defaultpubtype, 1, XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('sortpubtypes', 'isset', $sortpubtypes, 'id', XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('defaultlanguage', 'str:1:100', $defaultlanguage, xarModVars::get('publications', 'defaultlanguage'), XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('debugmode', 'checkbox', $debugmode, xarModVars::get('publications', 'debugmode'), XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('defaultfrontpage', 'str', $defaultfrontpage, xarModVars::get('publications', 'defaultfrontpage'), XARVAR_NOT_REQUIRED)) { return; } if (!xarVarFetch('defaultbackpage', 'str', $defaultbackpage, xarModVars::get('publications', 'defaultbackpage'), XARVAR_NOT_REQUIRED)) { return; } xarModVars::set('publications', 'defaultpubtype', $defaultpubtype); xarModVars::set('publications', 'sortpubtypes', $sortpubtypes); xarModVars::set('publications', 'defaultlanguage', $defaultlanguage); xarModVars::set('publications', 'debugmode', $debugmode); xarModVars::set('publications', 'usealias', $usealias); xarModVars::set('publications', 'usetitleforurl', $usetitleforurl); xarModVars::set('publications', 'defaultfrontpage', $defaultfrontpage); xarModVars::set('publications', 'defaultbackpage', $defaultbackpage); // Allow multilanguage only if the languages property is present sys::import('modules.dynamicdata.class.properties.registration'); $types = PropertyRegistration::Retrieve(); if (isset($types[30039])) { xarModVars::set('publications', 'multilanguage', $multilanguage); } else { xarModVars::set('publications', 'multilanguage', 0); } // Get the special pages. foreach (array('defaultpage', 'errorpage', 'notfoundpage', 'noprivspage') as $special_name) { unset($special_id); if (!xarVarFetch($special_name, 'id', $special_id, 0, XARVAR_NOT_REQUIRED)) { return; } xarModVars::set('publications', $special_name, $special_id); } if (xarDB::getType() == 'mysql') { if (!xarVarFetch('fulltext', 'isset', $fulltext, '', XARVAR_NOT_REQUIRED)) { return; } $oldval = xarModVars::get('publications', 'fulltextsearch'); $index = 'i_' . xarDB::getPrefix() . '_publications_fulltext'; if (empty($fulltext) && !empty($oldval)) { // Get database setup $dbconn = xarDB::getConn(); $xartable = xarDB::getTables(); $publicationstable = $xartable['publications']; // Drop fulltext index on publications table $query = "ALTER TABLE {$publicationstable} DROP INDEX {$index}"; $result =& $dbconn->Execute($query); if (!$result) { return; } xarModVars::set('publications', 'fulltextsearch', ''); } elseif (!empty($fulltext) && empty($oldval)) { $searchfields = array('title', 'description', 'summary', 'body1', 'notes'); // $searchfields = explode(',',$fulltext); // Get database setup $dbconn = xarDB::getConn(); $xartable = xarDB::getTables(); $publicationstable = $xartable['publications']; // Add fulltext index on publications table $query = "ALTER TABLE {$publicationstable} ADD FULLTEXT {$index} (" . join(', ', $searchfields) . ")"; $result =& $dbconn->Execute($query); if (!$result) { return; } xarModVars::set('publications', 'fulltextsearch', join(',', $searchfields)); } } // Module settings $data['module_settings'] = xarMod::apiFunc('base', 'admin', 'getmodulesettings', array('module' => 'publications')); $data['module_settings']->setFieldList('items_per_page, use_module_alias, module_alias_name, enable_short_urls, user_menu_link', 'use_module_icons'); $isvalid = $data['module_settings']->checkInput(); if (!$isvalid) { return xarTplModule('base', 'admin', 'modifyconfig', $data); } else { $itemid = $data['module_settings']->updateItem(); } // Pull the base category ids from the template and save them $picker = DataPropertyMaster::getProperty(array('name' => 'categorypicker')); $picker->checkInput('basecid'); } elseif ($data['tab'] == 'pubtypes') { // Get the publication type for this display and save the settings to it $pubtypeobject = DataObjectMaster::getObject(array('name' => 'publications_types')); $pubtypeobject->getItem(array('itemid' => $ptid)); $configsettings = $pubtypeobject->properties['configuration']->getValue(); $checkbox = DataPropertyMaster::getProperty(array('name' => 'checkbox')); $boxes = array('show_hitount', 'show_ratings', 'show_keywords', 'show_comments', 'show_prevnext', 'show_archives', 'show_publinks', 'show_pubcount', 'show_map', 'prevnextart', 'dot_transform', 'title_transform', 'show_categories', 'show_catcount', 'show_prevnext', 'allow_translations'); foreach ($boxes as $box) { $isvalid = $checkbox->checkInput($box); if ($isvalid) { $settings[$box] = $checkbox->value; } } // foreach ($configsettings as $key => $value) // if (!isset($settings[$key])) $settings[$key] = 0; $isvalid = true; // Get the default access rules $access = DataPropertyMaster::getProperty(array('name' => 'access')); $validprop = $access->checkInput("access_add"); $addaccess = $access->value; $isvalid = $isvalid && $validprop; $validprop = $access->checkInput("access_display"); $displayaccess = $access->value; $isvalid = $isvalid && $validprop; $validprop = $access->checkInput("access_modify"); $modifyaccess = $access->value; $isvalid = $isvalid && $validprop; $validprop = $access->checkInput("access_delete"); $deleteaccess = $access->value; $isvalid = $isvalid && $validprop; $allaccess = array('add' => $addaccess, 'display' => $displayaccess, 'modify' => $modifyaccess, 'delete' => $deleteaccess); $pubtypeobject->properties['access']->setValue(serialize($allaccess)); $pubtypeobject->properties['configuration']->setValue(serialize($settings)); $pubtypeobject->updateItem(array('itemid' => $ptid)); $pubtypes = xarModAPIFunc('publications', 'user', 'get_pubtypes'); if ($usealias) { xarModSetAlias($pubtypes[$ptid]['name'], 'publications'); } else { xarModDelAlias($pubtypes[$ptid]['name'], 'publications'); } } elseif ($data['tab'] == 'redirects') { $redirects = DataPropertyMaster::getProperty(array('name' => 'array')); $redirects->display_column_definition['value'] = array(array("From", "To"), array(2, 2), array("", ""), array("", "")); $isvalid = $redirects->checkInput("redirects"); xarModVars::set('publications', 'redirects', $redirects->value); } xarController::redirect(xarModURL('publications', 'admin', 'modifyconfig', array('ptid' => $ptid, 'tab' => $data['tab']))); 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; }
/** * Import an object definition or an object item from XML */ function publications_adminapi_importpubtype($args) { // Security check - we require ADMIN rights here if (!xarSecurityCheck('AdminPublications')) { return; } extract($args); if (empty($xml) && empty($file)) { $msg = xarML('Missing import file or XML content'); throw new BadParameterException(null, $msg); } elseif (!empty($file) && (!file_exists($file) || !preg_match('/\\.xml$/', $file))) { $msg = xarML('Invalid import file'); throw new BadParameterException(null, $msg); } $pubtypes = xarModAPIFunc('publications', 'user', 'get_pubtypes'); $proptypes = DataPropertyMaster::getPropertyTypes(); $name2id = array(); foreach ($proptypes as $propid => $proptype) { $name2id[$proptype['name']] = $propid; } $prefix = xarDB::getPrefix(); $prefix .= '_'; if (!empty($file)) { $fp = @fopen($file, 'r'); if (!$fp) { $msg = xarML('Unable to open import file'); throw new BadParameterException(null, $msg); } } else { $lines = preg_split("/\r?\n/", $xml); $maxcount = count($lines); } $what = ''; $count = 0; $ptid = 0; $objectname2objectid = array(); $objectcache = array(); $objectmaxid = array(); while (!empty($file) && !feof($fp) || !empty($xml) && $count < $maxcount) { if (!empty($file)) { $line = fgets($fp, 4096); } else { $line = $lines[$count]; } $count++; if (empty($what)) { if (preg_match('#<object name="(\\w+)">#', $line, $matches)) { // in case we import the object definition $object = array(); $object['name'] = $matches[1]; $what = 'object'; } elseif (preg_match('#<items>#', $line)) { // in case we only import data $what = 'item'; } } elseif ($what == 'object') { if (preg_match('#<([^>]+)>(.*)</\\1>#', $line, $matches)) { $key = $matches[1]; $value = $matches[2]; if (isset($object[$key])) { if (!empty($file)) { fclose($fp); } $msg = xarML('Duplicate definition for #(1) key #(2) on line #(3)', 'object', xarVarPrepForDisplay($key), $count); throw new DuplicateException(null, $msg); } $object[$key] = $value; } elseif (preg_match('#<config>#', $line)) { if (isset($object['config'])) { if (!empty($file)) { fclose($fp); } $msg = xarML('Duplicate definition for #(1) key #(2) on line #(3)', 'object', 'config', $count); throw new DuplicateException(null, $msg); } $config = array(); $what = 'config'; } elseif (preg_match('#<properties>#', $line)) { if (empty($object['name']) || empty($object['moduleid'])) { if (!empty($file)) { fclose($fp); } $msg = xarML('Missing keys in object definition'); throw new BadParameterException(null, $msg); } // make sure we drop the object id, because it might already exist here unset($object['objectid']); $properties = array(); $what = 'property'; } elseif (preg_match('#<items>#', $line)) { $what = 'item'; } elseif (preg_match('#</object>#', $line)) { $what = ''; } else { // multi-line entries not relevant here } } elseif ($what == 'config') { if (preg_match('#<([^>]+)>(.*)</\\1>#', $line, $matches)) { $key = $matches[1]; $value = $matches[2]; if (isset($config[$key])) { if (!empty($file)) { fclose($fp); } $msg = xarML('Duplicate definition for #(1) key #(2) on line #(3)', 'config', xarVarPrepForDisplay($key), $count); throw new DuplicateException(null, $msg); } $config[$key] = $value; } elseif (preg_match('#</config>#', $line)) { // override default view if necessary $config['defaultview'] = 1; $object['config'] = serialize($config); $config = array(); $what = 'object'; } else { // multi-line entries not relevant here } } elseif ($what == 'property') { if (preg_match('#<property name="(\\w+)">#', $line, $matches)) { $property = array(); $property['name'] = $matches[1]; } elseif (preg_match('#</property>#', $line)) { if (empty($property['name']) || empty($property['type'])) { if (!empty($file)) { fclose($fp); } $msg = xarML('Missing keys in property definition'); throw new BadParameterException(null, $msg); } // make sure we drop the property id, because it might already exist here unset($property['id']); // TODO: watch out for multi-sites // replace default xar_* table prefix with local one $property['source'] = preg_replace("/^xar_/", $prefix, $property['source']); // add this property to the list $properties[] = $property; } elseif (preg_match('#<([^>]+)>(.*)</\\1>#', $line, $matches)) { $key = $matches[1]; $value = $matches[2]; if (isset($property[$key])) { if (!empty($file)) { fclose($fp); } $msg = xarML('Duplicate definition for #(1) key #(2) on line #(3)', 'property', xarVarPrepForDisplay($key), $count); throw new DuplicateException(null, $msg); } $property[$key] = $value; } elseif (preg_match('#</properties>#', $line)) { // 1. make sure we have a unique pubtype name foreach ($pubtypes as $pubid => $pubtype) { if ($object['name'] == $pubtype['name']) { $object['name'] .= '_' . time(); break; } } // 2. fill in the pubtype field config $fields = array(); $extra = array(); foreach ($properties as $property) { $field = $property['name']; switch ($field) { case 'id': case 'pubtype_id': // skip these break; case 'title': case 'summary': case 'body': case 'notes': case 'owner': case 'pubdate': case 'state': // convert property type to string if necessary if (is_numeric($property['type'])) { if (isset($proptypes[$property['type']])) { $property['type'] = $proptypes[$property['type']]['name']; } else { $property['type'] = 'static'; } } // reset disabled field labels to empty if (empty($property['state'])) { $property['label'] = ''; } if (!isset($property['validation'])) { $property['validation'] = ''; } $fields[$field] = array('label' => $property['label'], 'format' => $property['type'], 'input' => $property['input'], 'validation' => $property['validation']); break; default: // convert property type to numeric if necessary if (!is_numeric($property['type'])) { if (isset($name2id[$property['type']])) { $property['type'] = $name2id[$property['type']]; } else { $property['type'] = 1; } } $extra[] = $property; break; } } // 3. create the pubtype $ptid = xarModAPIFunc('publications', 'admin', 'createpubtype', array('name' => $object['name'], 'descr' => $object['label'], 'config' => $fields)); if (empty($ptid)) { return; } // 4. set the module variables xarModVars::set('publications', 'settings.' . $ptid, $object['config']); xarModVars::set('publications', 'number_of_categories.' . $ptid, 0); xarModVars::set('publications', 'mastercids.' . $ptid, ''); // 5. create a dynamic object if necessary if (count($extra) > 0) { $object['itemtype'] = $ptid; $object['config'] = ''; $object['isalias'] = 0; $objectid = xarModAPIFunc('dynamicdata', 'admin', 'createobject', $object); if (!isset($objectid)) { if (!empty($file)) { fclose($fp); } return; } // 6. create the dynamic properties foreach ($extra as $property) { $property['objectid'] = $objectid; $property['moduleid'] = $object['moduleid']; $property['itemtype'] = $object['itemtype']; $prop_id = xarModAPIFunc('dynamicdata', 'admin', 'createproperty', $property); if (!isset($prop_id)) { if (!empty($file)) { fclose($fp); } return; } } // 7. check if we need to enable DD hooks for this pubtype if (!xarModIsHooked('dynamicdata', 'publications')) { xarModAPIFunc('modules', 'admin', 'enablehooks', array('callerModName' => 'publications', 'callerItemType' => $ptid, 'hookModName' => 'dynamicdata')); } } $properties = array(); $what = 'object'; } elseif (preg_match('#<items>#', $line)) { $what = 'item'; } elseif (preg_match('#</object>#', $line)) { $what = ''; } else { // multi-line entries not relevant here } } elseif ($what == 'item') { /* skip this for publications if (preg_match('#<([^> ]+) itemid="(\d+)">#',$line,$matches)) { // find out what kind of item we're dealing with $objectname = $matches[1]; $itemid = $matches[2]; if (empty($objectname2objectid[$objectname])) { $objectinfo = DataObjectMaster::getObjectInfo(array('name' => $objectname)); if (isset($objectinfo) && !empty($objectinfo['objectid'])) { $objectname2objectid[$objectname] = $objectinfo['objectid']; } else { if (!empty($file)) fclose($fp); $msg = xarML('Unknown #(1) "#(2)" on line #(3)','object',xarVarPrepForDisplay($objectname),$count); throw new BadParameterException(null, $msg); } } $objectid = $objectname2objectid[$objectname]; $item = array(); // don't save the item id for now... // TODO: keep the item id if we set some flag //$item['itemid'] = $itemid; $closeitem = $objectname; $closetag = 'N/A'; } elseif (preg_match("#</$closeitem>#",$line)) { // let's create the item now... if (!isset($objectcache[$objectid])) { $objectcache[$objectid] = new DataObject(array('objectid' => $objectid)); } // set the item id to 0 // TODO: keep the item id if we set some flag $item['itemid'] = 0; // create the item $itemid = $objectcache[$objectid]->createItem($item); if (empty($itemid)) { if (!empty($file)) fclose($fp); return; } // keep track of the highest item id if (empty($objectmaxid[$objectid]) || $objectmaxid[$objectid] < $itemid) { $objectmaxid[$objectid] = $itemid; } $closeitem = 'N/A'; $closetag = 'N/A'; } elseif (preg_match('#<([^>]+)>(.*)</\1>#',$line,$matches)) { $key = $matches[1]; $value = $matches[2]; if (isset($item[$key])) { if (!empty($file)) fclose($fp); $msg = xarML('Duplicate definition for #(1) key #(2) on line #(3)','item',xarVarPrepForDisplay($key),$count); throw new DuplicateException(null, $msg); } $item[$key] = $value; $closetag = 'N/A'; } elseif (preg_match('#<([^/>]+)>(.*)#',$line,$matches)) { // multi-line entries *are* relevant here $key = $matches[1]; $value = $matches[2]; if (isset($item[$key])) { if (!empty($file)) fclose($fp); $msg = xarML('Duplicate definition for #(1) key #(2)','item',xarVarPrepForDisplay($key)); throw new DuplicateException(null, $msg); } $item[$key] = $value; $closetag = $key; } elseif (preg_match("#(.*)</$closetag>#",$line,$matches)) { // multi-line entries *are* relevant here $value = $matches[1]; if (!isset($item[$closetag])) { if (!empty($file)) fclose($fp); $msg = xarML('Undefined #(1) key #(2)','item',xarVarPrepForDisplay($closetag)); throw new BadParameterException(null, $msg); } $item[$closetag] .= $value; $closetag = 'N/A'; } elseif ($closetag != 'N/A') { // multi-line entries *are* relevant here if (!isset($item[$closetag])) { if (!empty($file)) fclose($fp); $msg = xarML('Undefined #(1) key #(2)','item',xarVarPrepForDisplay($closetag)); throw new BadParameterException(null, $msg); } $item[$closetag] .= $line; } elseif (preg_match('#</items>#',$line)) { skip this for publications */ if (preg_match('#</items>#', $line)) { $what = 'object'; } elseif (preg_match('#</object>#', $line)) { $what = ''; } else { } } else { } } if (!empty($file)) { fclose($fp); } return $ptid; }
/** * 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; }
function publications_userapi_getpages($args) { extract($args); if (!xarVarValidate('enum:id:index:name:left:right', $key, true)) { $key = 'index'; } // Define if we are looking for the number of pages or the pages themselves $count = empty($count) ? false : true; // Assemble the query sys::import('xaraya.structures.query'); $xartable = xarDB::getTables(); $q = new Query(); $q->addtable($xartable['publications'], 'tpages'); $q->addtable($xartable['publications_types'], 'pt'); $q->join('pt.id', 'tpages.pubtype_id'); if ($count) { $q->addfield('COUNT(*)'); } else { $q->setdistinct(true); $q->addfield('tpages.id AS id'); $q->addfield('tpages.name AS name'); $q->addfield('tpages.title AS title'); $q->addfield('tpages.pubtype_id AS ptid'); $q->addfield('tpages.parent_id AS base_id'); $q->addfield('tpages.sitemap_flag AS sitemap_flag'); $q->addfield('tpages.menu_flag AS menu_flag'); $q->addfield('tpages.locale AS locale'); $q->addfield('tpages.leftpage_id AS leftpage_id'); $q->addfield('tpages.rightpage_id AS rightpage_id'); $q->addfield('tpages.parentpage_id AS parentpage'); $q->addfield('tpages.access AS access'); $q->addfield('tpages.state AS status'); $q->addfield('pt.description AS pubtype_name'); } if (isset($baseonly)) { $q->eq('tpages.parent_id', 0); } if (isset($name)) { $q->eq('tpages.name', (string) $name); } if (isset($status)) { // If a list of statuses have been provided, then select for any of them. if (strpos($status, ',') === false) { $numeric_status = convert_status($status); $q->eq('tpages.state', strtoupper($status)); } else { $statuses = explode(',', strtoupper($status)); $numeric_statuses = array(); foreach ($statuses as $stat) { $numeric_statuses[] = convert_status($stat); } $q->in('tpages.state', $numeric_statuses); } } if (isset($id)) { $q->eq('tpages.id', (int) $id); $where[] = 'tpages.id = ?'; $bind[] = (int) $id; } elseif (!empty($ids)) { $addwhere = array(); foreach ($ids as $myid) { if (!empty($myid) && is_numeric($myid)) { $addwhere[] = (int) $myid; } } $q->in('tpages.state', $addwhere); } if (isset($itemtype)) { $q->eq('tpages.pubtype_id', (int) $itemtype); } if (isset($parent)) { $q->eq('tpages.parentpage_id', (int) $parent); } // Used to retrieve descendants. if (isset($left_range) && is_array($left_range)) { $q->between('tpages.leftpage_id', $left_range); } // Used to prune a single branch of the tree. if (isset($left_exclude) && is_array($left_exclude)) { //'tpages.leftpage_id NOT between ? AND ?' - does not work on some databases $c[] = $q->plt('tpages.leftpage_id', (int) $left_exclude[0]); $c[] = $q->pgt('tpages.leftpage_id', (int) $left_exclude[1]); $q->qor($c); unset($c); } // Used to retrieve ancestors. if (isset($wrap_range) && is_numeric($wrap_range)) { $c[] = $q->ple('tpages.leftpage_id', (int) $wrap_range[0]); $c[] = $q->pge('tpages.leftpage_id', (int) $left_range[1]); // can't be right: this is an array $q->qand($c); unset($c); } // If the request is to fetch a tree that *contains* a particular // page, then add the extra sub-queries in here. if (!empty($tree_contains_id) || !empty($tree_contains_name)) { $q->addtable($xartable['publications'], 'tpages_member'); if (!empty($tree_contains_id)) { $q->eq('tpages_member.id', (int) $tree_contains_id); } if (!empty($tree_contains_name)) { $q->eq('tpages_member.name', (int) $tree_contains_name); } if (!empty($tree_ancestors)) { // We don't want the complete tree for the matching pages - just // their ancestors. This is useful for checking paths, without // fetching complete trees. $q->between('tpages_member.leftpage_id', 'expr:tpages.leftpage_id AND tpages.rightpage_id'); } else { // Join to find the root page of the tree containing the required page. // This matches the complete tree for the root under the selected page. $q->addtable($xartable['publications'], 'tpages_root'); $q->le('tpages_root.leftpage_id', 'expr:tpages_member.leftpage_id'); $q->ge('tpages_root.rightpage_id', 'expr:tpages_member.rightpage_id'); $q->between('tpages.leftpage_id', 'expr:tpages_root.leftpage_id AND tpages_root.rightpage_id'); $q->eq('tpages_root.parentpage_id', 0); } } // This ordering cannot be changed // We want the pages in the order of the hierarchy. if (empty($count)) { $q->setorder('tpages.leftpage_id', 'ASC'); } // $q->qecho(); $q->run(); if ($count) { $pages = count($q->output()); } else { $index = 0; $id2key = array(); $pages = array(); // Get all the page type details. $pagetypes = xarMod::apiFunc('publications', 'user', 'get_pubtypes', array('key' => 'id')); foreach ($q->output() as $row) { $id = (int) $row['id']; // At this point check the privileges of the page fetched. // To prevent broken trees, if a page is not assessible, prune // (ie discard) descendant pages of that page. Descendants will have // a left value between the left and right values of the // inaccessible page. if (!empty($prune_left)) { if ($row['leftpage_id'] <= $prune_left) { // The current page is still a descendant of the unprivileged page. continue; } else { // We've reached a non-descendant - stop pruning now. $prune_left = 0; } } // JDJ 2008-06-11: now only need ViewPublicationsPage to be able to select the page, // but ReadPublicationsPage to actually read it. // The lowest privilege will be inherited, so one page with only View privilege // will cause all descendent pages to have, at most, view privilege. // We still need to fetch full details of these view-only pages, but we must flag // then up in some way (status?). Displaying any of these pages would instead just // show the 'no privs' page. // Define admin access sys::import('modules.dynamicdata.class.properties.master'); $accessproperty = DataPropertyMaster::getProperty(array('name' => 'access')); $typename = $pagetypes[$row['ptid']]['name']; $args = array('instance' => $row['name'] . ":" . $typename, 'level' => 800); $adminaccess = $accessproperty->check($args); $info = unserialize($row['access']); if (!empty($info['view_access'])) { // Decide whether the current user can create blocks of this type $args = array('module' => 'publications', 'component' => 'Page', 'instance' => $name . ":" . $typename, 'group' => $info['view_access']['group'], 'level' => $info['view_access']['level']); if (!$accessproperty->check($args)) { // Save the right value. We need to skip all subsequent // pages until we get to a page to the right of this one. // The pages will be in 'left' order, so the descendants // will be contiguous and will immediately follow this page. $prune_left = $rightpage_id; // Don't get this unless you are an admin if (!$adminaccess) { continue; } } } if (!empty($overview_only_left) && $row['leftpage_id'] <= $overview_only_left) { // We have got past the overview-only page, so can reset the flag. $overview_only_left = 0; } if (!empty($info['display_access'])) { $args = array('module' => 'publications', 'component' => 'Page', 'instance' => $name . ":" . $typename, 'group' => $info['display_access']['group'], 'level' => $info['display_access']['level']); if (!$accessproperty->check($args)) { // We have reached a page that allows only overview access. // Flag all pages with the restricted view until we get past this page. $overview_only_left = $row['rightpage_id']; // Don't get this unless you are an admin if (!$adminaccess) { continue; } } } if (!xarSecurityCheck('ReadPublications', 0, 'Page', $row['name'] . ':' . $typename, 'publications')) { // We have reached a page that allows only overview access. // Flag all pages with the restricted view until we get past this page. $overview_only_left = $row['rightpage_id']; } // Note: ['parent_id'] is the parent page ID, // but ['parent'] is the parent item key in the // pages array. $id2key[(int) $id] = ${$key}; if ($key == 'id') { $parent_key = (int) $row['parentpage']; } else { if (isset($id2key[$row['parentpage']])) { $parent_key = $id2key[$row['parentpage']]; } else { $parent_key = 0; } } $row['key'] = ${$key}; $row['access'] = $info; $row['parent_key'] = (int) $parent_key; $row['left'] = (int) $row['leftpage_id']; $row['right'] = (int) $row['rightpage_id']; unset($row['leftpage_id']); unset($row['rightpage_id']); $pages[${$key}] = $row; $index += 1; } } return $pages; }
function publications_treeapi_insertprep($args) { // An insertion point (an ID in the table) is required. // Special insertion point ID is 0, which refers to the // virtual root of all trees. An item can not be // inserted on the same level as the virtual root. extract($args); // TODO: validate params: insertpoint, offset, tablename, idname // Default operation is 'before' - i.e. put the new item in the place // of the insertpoint and move everything to the right one place. if (!xarVarValidate('enum:before:after:firstchild:lastchild', $offset, true)) { $offset = 'firstchild'; } if (!isset($insertpoint)) { $insertpoint = 0; } if (!isset($idname)) { $idname = 'xar_id'; } // Cannot insert on the same level as the virtual root. if ($insertpoint == 0) { if ($offset == 'before') { $offset = 'firstchild'; } if ($offset == 'after') { $offset = 'lastchild'; } } $dbconn = xarDB::getConn(); $result = xarMod::apiFunc('publications', 'tree', 'getleftright', array('tablename' => $tablename, 'idname' => $idname, 'id' => $insertpoint)); if (!$result) { return; } extract($result); // Locate the new insert point. if ($offset == 'before') { $shift = $left; } if ($offset == 'after') { $shift = $right + 1; } if ($offset == 'firstchild') { $shift = $left + 1; $parent = $insertpoint; } if ($offset == 'lastchild') { $shift = $right; $parent = $insertpoint; } // Create a space of two traversal points. // The new item will not have children, so the traversal // points will be sequential. $query = 'UPDATE ' . $tablename . ' SET xar_left = xar_left + 2 ' . ' WHERE xar_left >= ?'; $result = $dbconn->execute($query, array($shift)); if (!$result) { return; } $query = 'UPDATE ' . $tablename . ' SET xar_right = xar_right + 2 ' . ' WHERE xar_right >= ?'; $result = $dbconn->execute($query, array($shift)); if (!$result) { return; } // Return the new parent/left/right values return array('parent' => $parent, 'left' => $shift, 'right' => $shift + 1); }
public function getEvents($start_time, $end_time, $role_id) { // get all the events. need to improve this query and combine it with the query in the template $xartable = xarDB::getTables(); $q = new Query('SELECT', $xartable['calendar_event']); $q->ge('start_time', $start_time); $q->lt('start_time', $end_time); $q->eq('role_id', $role_id); // $q->qecho(); if (!$q->run()) { return; } return $q->output(); }
/** * 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; }
/** * Publications Module * * @package modules * @subpackage publications module * @category Third Party Xaraya Module * @version 2.0.0 * @copyright (C) 2011 Netspan AG * @license GPL {@link http://www.gnu.org/licenses/gpl.html} * @author Marc Lutolf <*****@*****.**> */ function publications_admin_clone() { if (!xarSecurityCheck('ManagePublications')) { return; } if (!xarVarFetch('name', 'isset', $objectname, NULL, XARVAR_DONT_SET)) { return; } if (!xarVarFetch('ptid', 'isset', $ptid, NULL, XARVAR_DONT_SET)) { return; } if (!xarVarFetch('itemid', 'isset', $data['itemid'], NULL, XARVAR_DONT_SET)) { return; } if (!xarVarFetch('confirm', 'int', $confirm, 0, XARVAR_DONT_SET)) { return; } if (empty($data['itemid'])) { return xarResponse::NotFound(); } // If a pubtype ID was passed, get the name of the pub object if (isset($ptid)) { $pubtypeobject = DataObjectMaster::getObject(array('name' => 'publications_types')); $pubtypeobject->getItem(array('itemid' => $ptid)); $objectname = $pubtypeobject->properties['name']->value; } if (empty($objectname)) { return xarResponse::NotFound(); } sys::import('modules.dynamicdata.class.objects.master'); $data['object'] = DataObjectMaster::getObject(array('name' => $objectname)); if (empty($data['object'])) { return xarResponse::NotFound(); } // Security if (!$data['object']->checkAccess('update')) { return xarResponse::Forbidden(xarML('Clone #(1) is forbidden', $object->label)); } $data['object']->getItem(array('itemid' => $data['itemid'])); $data['authid'] = xarSecGenAuthKey(); $data['name'] = $data['object']->properties['name']->value; $data['label'] = $data['object']->label; xarTplSetPageTitle(xarML('Clone Publication #(1) in #(2)', $data['itemid'], $data['label'])); if ($confirm) { if (!xarSecConfirmAuthKey()) { return; } // Get the name for the clone if (!xarVarFetch('newname', 'str', $newname, "", XARVAR_NOT_REQUIRED)) { return; } if (empty($newname)) { $newname = $data['name'] . "_copy"; } if ($newname == $data['name']) { $newname = $data['name'] . "_copy"; } $newname = strtolower(str_ireplace(" ", "_", $newname)); // Create the clone $data['object']->properties['name']->setValue($newname); $data['object']->properties['id']->setValue(0); $cloneid = $data['object']->createItem(array('itemid' => 0)); // Create the clone's translations if (!xarVarFetch('clone_translations', 'int', $clone_translations, 0, XARVAR_NOT_REQUIRED)) { return; } if ($clone_translations) { // Get the info on all the objects to be cloned sys::import('xaraya.structures.query'); $tables = xarDB::getTables(); $q = new Query(); $q->addtable($tables['publications'], 'p'); $q->addtable($tables['publications_types'], 'pt'); $q->join('p.pubtype_id', 'pt.id'); $q->eq('parent_id', $data['itemid']); $q->addfield('p.id AS id'); $q->addfield('pt.name AS name'); $q->run(); // Clone each one foreach ($q->output() as $item) { $object = DataObjectMaster::getObject(array('name' => $item['name'])); $object->getItem(array('itemid' => $item['id'])); $object->properties['parent']->value = $cloneid; $object->properties['id']->value = 0; $object->createItem(array('itemid' => 0)); } } // Redirect if we came from somewhere else $current_listview = xarSession::getVar('publications_current_listview'); if (!empty($return_url)) { xarController::redirect($return_url); } elseif (!empty($current_listview)) { xarController::redirect($current_listview); } else { xarController::redirect(xarModURL('publications', 'user', 'view')); } return true; } return $data; }
function publications_treeapi_moveitem($args) { extract($args); $dbconn = xarDB::getConn(); $xartable = xarDB::getTables(); // Obtain current information on the reference item $refitem = xarMod::apiFunc('publications', 'user', 'getpage', array('pid' => $refid)); $query = 'SELECT xar_left, xar_right, xar_parent' . ' FROM ' . $tablename . ' WHERE ' . $idname . ' = ?'; // Run the query (reference item). $result = $dbconn->execute($query, array($refid)); if (!$result) { return; } if ($result->EOF) { $msg = xarML('Reference item "#(1)" does not exist', $refid); throw new BadParameterException(null, $msg); } list($ref_left, $ref_right, $ref_parent) = $result->fields; // Run the query (item to be moved). $result = $dbconn->execute($query, array((int) $itemid)); if (!$result) { return; } if ($result->EOF) { $msg = xarML('Moving item "#(1)" does not exist', $itemid); throw new BadParameterException(null, $msg); } list($item_left, $item_right, $item_parent) = $result->fields; // Checking if the reference ID is of a child or itself if ($ref_left >= $item_left && $ref_left <= $item_right) { $msg = xarML('Group references siblings'); throw new BadParameterException(null, $msg); } // Find the point of insertion. switch (strtolower($offset)) { case 'lastchild': // last child of reference item $insertion_point = $ref_right; break; case 'after': // after reference item, same level $insertion_point = $ref_right + 1; break; case 'firstchild': // first child reference item $insertion_point = $ref_left + 1; break; case 'before': // before reference item, same level $insertion_point = $ref_left; break; default: $msg = xarML('Offset not "#(1)" valid', $offset); throw new BadParameterException(null, $msg); } $size = $item_right - $item_left + 1; $distance = $insertion_point - $item_left; // If necessary to move then evaluate if ($distance != 0) { if ($distance > 0) { // moving forward $distance = $insertion_point - $item_right - 1; $deslocation_outside = -$size; $between_string = $item_right + 1 . ' AND ' . ($insertion_point - 1); } else { // $distance < 0 (moving backward) $deslocation_outside = $size; $between_string = $insertion_point . ' AND ' . ($item_left - 1); } // This seems SQL-92 standard... Its a good test to see if // the databases we are supporting are complying with it. This can be // broken down in 3 simple UPDATES which shouldnt be a problem with any database. $query = 'UPDATE ' . $tablename . ' SET xar_left = CASE' . ' WHEN xar_left BETWEEN ' . $item_left . ' AND ' . $item_right . ' THEN xar_left + (' . $distance . ')' . ' WHEN xar_left BETWEEN ' . $between_string . ' THEN xar_left + (' . $deslocation_outside . ')' . ' ELSE xar_left' . ' END,' . ' xar_right = CASE' . ' WHEN xar_right BETWEEN ' . $item_left . ' AND ' . $item_right . ' THEN xar_right + (' . $distance . ')' . ' WHEN xar_right BETWEEN ' . $between_string . ' THEN xar_right + (' . $deslocation_outside . ')' . ' ELSE xar_right' . ' END'; $result = $dbconn->execute($query); if (!$result) { return; } // Find the right parent for this item. if (strtolower($offset) == 'lastchild' || strtolower($offset) == 'firstchild') { $parent_id = $refid; } else { $parent_id = $ref_parent; } // Update parent id $query = 'UPDATE ' . $tablename . ' SET xar_parent = ?' . ' WHERE ' . $idname . ' = ?'; $result = $dbconn->execute($query, array((int) $parent_id, (int) $itemid)); if (!$result) { return; } } return true; }
function calendar_user_day() { $data = xarMod::apiFunc('calendar', 'user', 'getUserDateTimeInfo'); $DayEvents = new Calendar_Day($data['cal_year'], $data['cal_month'], $data['cal_day'], CALENDAR_FIRST_DAY_OF_WEEK); $args = array('day' => &$Day); $day_endts = $DayEvents->getTimestamp() + xarModVars::get('calendar', 'day_end') + 3600; // $events = xarMod::apiFunc('icalendar','user','getevents',$args); // get all the events. need to improve this query $xartable = xarDB::getTables(); $q = new Query('SELECT', $xartable['calendar_event']); // $q->qecho(); if (!$q->run()) { return; } $events = $q->output(); // Do some calculations to complete the entries' info $slots = array(); // Loop through the events $eventcount = count($events); for ($j = 0; $j < $eventcount; $j++) { // make sure events don't go past the end of the day $events[$j]['end_time'] = min($events[$j]['end_time'], $day_endts); $placed = false; $slotcount = count($slots); for ($i = 0; $i < $slotcount; $i++) { if ($events[$j]['start_time'] >= $slots[$i][1]) { foreach ($slots as $slot) { $events[$slot[0]]['neighbors'] = $slotcount; } $thisslot = $i; $slots = array(0 => array($j, $events[$j]['end_time'])); $placed = true; break; } } if (!$placed) { $thisslot = $slotcount; $slots[] = array($j, $events[$j]['end_time']); } $events[$j]['place'] = $thisslot; } foreach ($slots as $slot) { $events[$slot[0]]['neighbors'] = $slotcount; } //foreach($events as $event) {var_dump($event);echo "<br />";} /* $selection = array(); foreach ( $entries as $entry ) { $Hour = new Calendar_Hour(2000,1,1,1); $Hour->setTimeStamp($entry['start_time']); // Create the decorator, passing it the Hour $event = new Event($Hour); // Attach the payload $event->setEntry($entry); // Add the decorator to the selection $selection[] = $event; } */ $DayDecorator = new DayEvent_Decorator($DayEvents); $DayDecorator->build($events); $data['Day'] =& $DayDecorator; $data['cal_sdow'] = CALENDAR_FIRST_DAY_OF_WEEK; return $data; }