Fix for #2107 - In CCWeb->Browse, selecting a value from the third column does not refine the search. In fact the code for browse was seriously broken. It has all been fixed, and is easier to understand. I also optimized the code, there is now (number_of_results)*2 fewer database calls for this screen - instead there are only 2 database calls for the entire list of results. Therefore the Browse screen should be visibly faster. The result ordering now takes into account the track number, the complete order is now: creator, album, track number, title. The album name and track number have been added to the search results. In DataEngine.php, I broke up the function _localGenSearch() into two functions: one for searching and one for fetching the column values (new function: _browseCategory()). These two things are completely separate tasks and doing this separation makes the code much easier to understand. Added lots of code documentation to htmlUI/var/ui_browse.class.php.
This commit is contained in:
parent
b5540ad4f0
commit
02b5c32098
|
@ -370,7 +370,7 @@ table {
|
|||
|
||||
table td {
|
||||
font-size: 12px;
|
||||
padding: 0 6px 0 12px;
|
||||
padding: 2px 6px 0px 6px;
|
||||
border-right: 1px solid #333;
|
||||
height: 19px;
|
||||
vertical-align: top;
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
body {
|
||||
body {
|
||||
font-family: Arial, Verdana, Helvetica, sans-serif;
|
||||
font-size: 12px;
|
||||
color: #2C2C2C;
|
||||
margin: 10px;
|
||||
}
|
||||
|
||||
img {
|
||||
img {
|
||||
border: none;
|
||||
}
|
||||
|
||||
|
@ -137,7 +137,8 @@ table tr.blue_head td { font-size: 12px;
|
|||
|
||||
}
|
||||
|
||||
A#blue_head { font-size: 12px;
|
||||
A#blue_head {
|
||||
font-size: 12px;
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
|
@ -230,7 +231,7 @@ table tr.red td { font-size: 12px;
|
|||
margin-left: 200px;
|
||||
}
|
||||
|
||||
label {
|
||||
label {
|
||||
display: block;
|
||||
float: left;
|
||||
width: 100px;
|
||||
|
@ -370,14 +371,15 @@ table td { font-size: 12px;
|
|||
vertical-align: top;
|
||||
}
|
||||
|
||||
table tr.blue_head td { font-size: 12px;
|
||||
table tr.blue_head td {
|
||||
font-size: 12px;
|
||||
background-color: #8baed1;
|
||||
color: #FFF;
|
||||
font-weight: bold;
|
||||
|
||||
}
|
||||
|
||||
A#blue_head { font-size: 12px;
|
||||
A#blue_head {
|
||||
font-size: 12px;
|
||||
color:#fff;
|
||||
}
|
||||
|
||||
|
|
|
@ -8,13 +8,15 @@
|
|||
{if $_results.cnt > 0}
|
||||
<form name="SEARCHRESULTS">
|
||||
<div class="head" style="width:600px; height: 21px;"> </div>
|
||||
<div class="container_table" style="width: 600px; height: auto;">
|
||||
<div class="container_table" style="width: 600px; height: auto;">
|
||||
|
||||
<table style="width: 600px;">
|
||||
<tr class="blue_head">
|
||||
<td style="width: 30px"><input type="checkbox" name="all" onClick="collector_switchAll('SEARCHRESULTS')"></td>
|
||||
<td style="width: 20px"><input type="checkbox" name="all" onClick="collector_switchAll('SEARCHRESULTS')"></td>
|
||||
<td style="width: 200px;"><a href="#" onClick="hpopup('{$UI_HANDLER}?act={$_act_prefix}.reorder&by=title', 'order');" id="blue_head">##Title##</a></td>
|
||||
<td style="width: 195px"><a href="#" onClick="hpopup('{$UI_HANDLER}?act={$_act_prefix}.reorder&by=creator', 'order');" id="blue_head">##Creator##</a></td>
|
||||
<td style="width: 195px">##Album##</td>
|
||||
<td style="width: 25px">##Track##</td>
|
||||
<td><a href="#" onClick="hpopup('{$UI_HANDLER}?act={$_act_prefix}.reorder&by=extent', 'order');" id="blue_head">##Duration##</a></td>
|
||||
<td style="width: 41px; border: 0; text-align: center"><a href="#" onClick="hpopup('{$UI_HANDLER}?act={$_act_prefix}.reorder&by=type', 'order');" id="blue_head">##Type##</a></td>
|
||||
</tr>
|
||||
|
@ -30,6 +32,8 @@
|
|||
{/if}
|
||||
</td>
|
||||
<td {include file=$action_handler} style="cursor: pointer">{$i.creator}</td>
|
||||
<td {include file=$action_handler} style="cursor: pointer">{$i.source}</td>
|
||||
<td {include file=$action_handler} style="cursor: pointer" align="center">{$i.track_num}</td>
|
||||
<td {include file=$action_handler} style="text-align: right; cursor: pointer">{assign var="_duration" value=$i.duration}{niceTime in=$_duration}</td>
|
||||
<td {include file=$action_handler} style="border: 0; text-align: center; cursor: pointer">
|
||||
<img src="img/{$i.type|lower}.png" border="0" alt="{$i.type|lower|capitalize}" {* include file="sub/alttext.tpl" *} />
|
||||
|
|
|
@ -7,9 +7,47 @@
|
|||
class uiBrowse
|
||||
{
|
||||
public $Base; // uiBase object
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $prefix;
|
||||
|
||||
/**
|
||||
* A pointer to the SESSION variable: ['UI_BROWSE_SESSNAME']['col']
|
||||
*
|
||||
* It has the following structure:
|
||||
* The first index denotes which column you are referring to.
|
||||
* There are three possible columns.
|
||||
*
|
||||
* For each column, the following keys are possible:
|
||||
* ['category'] --> selected category
|
||||
* ['value'] --> an array of one value, the selected value
|
||||
* ['values']['cnt'] --> number of values
|
||||
* ['values']['results'] --> array of values, indexed numerically
|
||||
* ['criteria'] --> criteria for one column, see top of DataEngine.php
|
||||
* for description of these values. The criteria of all three
|
||||
* columns are merged together to make $this->criteria.
|
||||
* ['form_value'] --> the value as used in the HTML form
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $col;
|
||||
|
||||
/**
|
||||
* A pointer to the SESSION variable: ['UI_BROWSE_SESSNAME']['criteria']
|
||||
*
|
||||
* This array ultimately is passed to DataEngine::localSearch(). Look
|
||||
* at the top of the DataEngine.php class for the structure of this
|
||||
* variable.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $criteria;
|
||||
|
||||
/**
|
||||
* @var string
|
||||
*/
|
||||
private $reloadUrl;
|
||||
|
||||
|
||||
|
@ -42,6 +80,12 @@ class uiBrowse
|
|||
} // fn setReload
|
||||
|
||||
|
||||
/**
|
||||
* Initialize $this->col. Each column contains
|
||||
*
|
||||
* @param boolean $reload
|
||||
* @return void
|
||||
*/
|
||||
public function setDefaults($reload=FALSE)
|
||||
{
|
||||
$this->col[1]['category'] = UI_BROWSE_DEFAULT_KEY_1;
|
||||
|
@ -69,12 +113,18 @@ class uiBrowse
|
|||
} // fn setDefaults
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getCriteria()
|
||||
{
|
||||
return $this->criteria;
|
||||
} // fn getCriteria
|
||||
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function getResult()
|
||||
{
|
||||
$this->searchDB();
|
||||
|
@ -85,7 +135,6 @@ class uiBrowse
|
|||
public function browseForm($id, $mask2)
|
||||
{
|
||||
include(dirname(__FILE__).'/formmask/metadata.inc.php');
|
||||
#$mask2['browse_columns']['category']['options'][0] = tra('Select a Value');
|
||||
foreach ($mask['pages'] as $key => $val) {
|
||||
foreach ($mask['pages'][$key] as $v){
|
||||
if (isset($v['type']) && $v['type']) {
|
||||
|
@ -93,7 +142,7 @@ class uiBrowse
|
|||
$mask2['browse_columns']['category']['options'][$tmp] = tra($v['label']);
|
||||
}
|
||||
}
|
||||
};
|
||||
}
|
||||
|
||||
for ($n = 1; $n <= 3; $n++) {
|
||||
$form = new HTML_QuickForm('col'.$n, UI_STANDARD_FORM_METHOD, UI_HANDLER);
|
||||
|
@ -109,7 +158,7 @@ class uiBrowse
|
|||
$output['col'.$n]['dynform'] = $renderer->toArray();
|
||||
}
|
||||
|
||||
## form to change limit and file-type
|
||||
// form to change limit and file-type
|
||||
$form = new HTML_QuickForm('switch', UI_STANDARD_FORM_METHOD, UI_HANDLER);
|
||||
uiBase::parseArrayToForm($form, $mask2['browse_global']);
|
||||
$form->setDefaults(array('limit' => $this->criteria['limit'],
|
||||
|
@ -124,68 +173,101 @@ class uiBrowse
|
|||
|
||||
/**
|
||||
* Set the category for audio file browser. There are three columns
|
||||
* you can set the category for.
|
||||
* you can set the category for. All columns greater than the current
|
||||
* one will be cleared of their values.
|
||||
*
|
||||
* @param array $parm
|
||||
* @param array $p_param
|
||||
* Has keys:
|
||||
* int ['col'] - the column you are setting the category for
|
||||
* string ['category'] - the category for the given column
|
||||
* string ['value'] - the search value for the given category
|
||||
* @return void
|
||||
*/
|
||||
public function setCategory($parm)
|
||||
public function setCategory($p_param)
|
||||
{
|
||||
$columnNumber = $parm['col'];
|
||||
$category = $parm['category'];
|
||||
// input values
|
||||
$columnNumber = $p_param['col'];
|
||||
$category = uiBase::formElementDecode($p_param['category']);
|
||||
|
||||
$this->col[$columnNumber]['category'] = uiBase::formElementDecode($category);
|
||||
$criteria = isset($this->col[$columnNumber]['criteria']) ? $this->col[$columnNumber]['criteria'] : null;
|
||||
$this->col[$columnNumber]['values'] = $this->Base->gb->browseCategory($this->col[$columnNumber]['category'], $criteria, $this->Base->sessid);
|
||||
// Set the new values for this column.
|
||||
$this->col[$columnNumber]['category'] = $category;
|
||||
$this->col[$columnNumber]['criteria'] = NULL;
|
||||
$this->col[$columnNumber]['form_value'] = '%%all%%';
|
||||
|
||||
// Get the values of this category based on the criteria in the
|
||||
// other columns.
|
||||
$this->setCriteria();
|
||||
$tmpCriteria = $this->criteria;
|
||||
// We put a limit here to because some categories will select
|
||||
// way too many values.
|
||||
$tmpCriteria["limit"] = 1000;
|
||||
$tmpCriteria["offset"] = 0;
|
||||
$browseValues = $this->Base->gb->browseCategory(
|
||||
$category, $tmpCriteria, $this->Base->sessid);
|
||||
if (!PEAR::isError($browseValues)) {
|
||||
$this->col[$columnNumber]['values'] = $browseValues;
|
||||
}
|
||||
|
||||
$this->Base->redirUrl = UI_BROWSER.'?act='.$this->prefix;
|
||||
$this->clearHierarchy($columnNumber);
|
||||
} // fn setCategory
|
||||
|
||||
|
||||
/**
|
||||
* Set the value for a category. This will cause the
|
||||
* search results to change.
|
||||
*
|
||||
* @param array $parm
|
||||
* contains the following indexes:
|
||||
* int ['col']: column number
|
||||
* string ['value'][0]: the search value for the given category
|
||||
* string ['category']: the category to search
|
||||
* @see DataEngine
|
||||
* See the top of that file for a description of the search
|
||||
* criteria structure.
|
||||
*/
|
||||
public function setValue($parm)
|
||||
public function setValue($p_param)
|
||||
{
|
||||
$this->criteria['offset'] = 0;
|
||||
$columnNumber = $parm['col'];
|
||||
$next = $columnNumber + 1;
|
||||
$this->col[$columnNumber]['form_value'] = $parm['value'][0];
|
||||
$tmpFiletype = isset($this->criteria['filetype'])?$this->criteria['filetype']:UI_FILETYPE_ANY;
|
||||
if ($parm['value'][0] == '%%all%%') {
|
||||
$this->col[$next]['criteria'] = array('operator' => 'and',
|
||||
'filetype' => $tmpFiletype);
|
||||
} else {
|
||||
$conditions = array(
|
||||
array('cat' => uiBase::formElementDecode($parm['category']),
|
||||
'op' => '=',
|
||||
'val' => $parm['value'][0]
|
||||
));
|
||||
if (isset($this->col[$columnNumber]['criteria']['conditions'])
|
||||
&& is_array($this->col[$columnNumber]['criteria']['conditions'])) {
|
||||
$conditions = array_merge($conditions,
|
||||
$this->col[$columnNumber]['criteria']['conditions']);
|
||||
}
|
||||
$this->col[$next]['criteria'] = array(
|
||||
'operator' => 'and',
|
||||
'filetype' => $this->criteria['filetype'],
|
||||
'conditions' => $conditions);
|
||||
}
|
||||
$nextCriteria = isset($this->col[$next]['criteria']) ? $this->col[$next]['criteria'] : null;
|
||||
$category = isset($this->col[$next]['category']) ? $this->col[$next]['category'] : null;
|
||||
$this->col[$next]['values'] = $this->Base->gb->browseCategory($category, $nextCriteria, $this->Base->sessid);
|
||||
$columnNumber = $p_param['col'];
|
||||
$value = $p_param['value'][0];
|
||||
$category = $p_param['category'];
|
||||
|
||||
$this->criteria['offset'] = 0;
|
||||
$this->col[$columnNumber]['form_value'] = $value;
|
||||
|
||||
if ($value == '%%all%%') {
|
||||
unset($this->col[$columnNumber]['criteria']['conditions']);
|
||||
} else {
|
||||
$conditions = array('cat' => uiBase::formElementDecode($category),
|
||||
'op' => '=',
|
||||
'val' => $value);
|
||||
$this->col[$columnNumber]['criteria']['conditions'] = $conditions;
|
||||
}
|
||||
|
||||
// Update the criteria
|
||||
$this->setCriteria();
|
||||
$this->clearHierarchy($next);
|
||||
$tmpCriteria = $this->criteria;
|
||||
// We put a limit here to because some categories will select
|
||||
// way too many values.
|
||||
$tmpCriteria["limit"] = 1000;
|
||||
$tmpCriteria["offset"] = 0;
|
||||
|
||||
// We need to update all other column values for any column
|
||||
// that does not have a selected value.
|
||||
for ($tmpColNum = 1; $tmpColNum <= 3; $tmpColNum++) {
|
||||
// Make sure not to update current column
|
||||
if ($tmpColNum != $columnNumber) {
|
||||
// if the column does not have a selected value
|
||||
if ($this->col[$tmpColNum]['criteria'] == NULL) {
|
||||
$tmpCategory = $this->col[$tmpColNum]['category'];
|
||||
$browseValues = $this->Base->gb->browseCategory(
|
||||
$tmpCategory, $tmpCriteria, $this->Base->sessid);
|
||||
if (!PEAR::isError($browseValues)) {
|
||||
$this->col[$tmpColNum]['values'] = $browseValues;
|
||||
$this->col[$tmpColNum]['criteria'] = NULL;
|
||||
$this->col[$tmpColNum]['form_value'] = '%%all%%';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$this->Base->redirUrl = UI_BROWSER.'?act='.$this->prefix;
|
||||
} // fn setValue
|
||||
|
||||
|
@ -211,31 +293,18 @@ class uiBrowse
|
|||
|
||||
|
||||
/**
|
||||
* Clear all categories from the given column number to column 3.
|
||||
*
|
||||
* @param int $columnNumber
|
||||
* Reload the conditions as set in the three columns.
|
||||
* @return void
|
||||
*/
|
||||
private function clearHierarchy($columnNumber)
|
||||
{
|
||||
$this->col[$columnNumber]['form_value'] = NULL;
|
||||
$columnNumber++;
|
||||
for ($col = $columnNumber; $col <= 3; $col++) {
|
||||
$this->col[$col]['criteria'] = NULL;
|
||||
$this->col[$col]['values'] = NULL;
|
||||
$this->col[$col]['form_value'] = NULL;
|
||||
}
|
||||
} // fn clearHierarchy
|
||||
|
||||
|
||||
public function setCriteria() {
|
||||
unset($this->criteria['conditions']);
|
||||
$conditions = array();
|
||||
for ($col = 3; $col >= 1; $col--) {
|
||||
if (is_array($this->col[$col]['criteria'])) {
|
||||
$this->criteria = array_merge($this->col[$col]['criteria'], $this->criteria);
|
||||
break;
|
||||
if (is_array($this->col[$col]['criteria']['conditions'])) {
|
||||
$conditions[] = $this->col[$col]['criteria']['conditions'];
|
||||
}
|
||||
}
|
||||
$this->criteria['conditions'] = $conditions;
|
||||
} // fn setCriteria
|
||||
|
||||
|
||||
|
@ -247,34 +316,9 @@ class uiBrowse
|
|||
if (!is_array($results) || !count($results)) {
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->results['cnt'] = $results['cnt'];
|
||||
foreach ($results['results'] as $rec) {
|
||||
$tmpId = BasicStor::IdFromGunid($rec["gunid"]);
|
||||
$this->results['items'][] = $this->Base->getMetaInfo($tmpId);
|
||||
}
|
||||
|
||||
/*
|
||||
## test
|
||||
for ($n=0; $n<=$this->criteria['limit']; $n++) {
|
||||
$this->results['items'][] = Array
|
||||
(
|
||||
'id' => 24,
|
||||
'gunid' => '1cc472228d0cb2ac',
|
||||
'title' => 'Item '.$n,
|
||||
'creator' => 'Sebastian',
|
||||
'duration' => ' 10:00',
|
||||
'type' => 'webstream'
|
||||
);
|
||||
}
|
||||
$results['cnt'] = 500;
|
||||
$this->results['cnt'] = $results['cnt'];
|
||||
## end test
|
||||
*/
|
||||
|
||||
$this->results['items'] = $results['results'];
|
||||
$this->pagination($results);
|
||||
#print_r($this->criteria);
|
||||
#print_r($this->results);
|
||||
return TRUE;
|
||||
} // fn searchDB
|
||||
|
||||
|
@ -370,18 +414,31 @@ class uiBrowse
|
|||
} // fn setLimit
|
||||
|
||||
|
||||
public function setFiletype($filetype)
|
||||
public function setFiletype($p_filetype)
|
||||
{
|
||||
$this->criteria['filetype'] = $filetype;
|
||||
$this->criteria['filetype'] = $p_filetype;
|
||||
$this->criteria['offset'] = 0;
|
||||
|
||||
for ($n = 1; $n <= 3; $n++) {
|
||||
$this->col[$n]['criteria']['filetype'] = $filetype;
|
||||
$this->col[$n]['values'] = $this->Base->gb->browseCategory($this->col[$n]['category'], $this->col[$n]['criteria'], $this->Base->sessid);
|
||||
$this->clearHierarchy($n);
|
||||
$this->col[$n]['form_value'] = '%%all%%';
|
||||
$this->col[$n]['criteria'] = null;
|
||||
}
|
||||
$this->setCriteria();
|
||||
$tmpCriteria = $this->criteria;
|
||||
$tmpCriteria["limit"] = 1000;
|
||||
|
||||
for ($n = 1; $n <= 3; $n++) {
|
||||
$browseValues = $this->Base->gb->browseCategory(
|
||||
$this->col[$n]['category'],
|
||||
$tmpCriteria,
|
||||
$this->Base->sessid);
|
||||
if (!PEAR::isError($browseValues)) {
|
||||
$this->col[$n]['values'] = $browseValues;
|
||||
}
|
||||
}
|
||||
|
||||
$this->setReload();
|
||||
} // fn setFiletype
|
||||
|
||||
} // class uiBrowse
|
||||
?>
|
|
@ -116,7 +116,6 @@ class uiSearch
|
|||
|
||||
function newSearch(&$formdata)
|
||||
{
|
||||
#print_r($formdata);
|
||||
$this->results = NULL;
|
||||
$this->criteria['conditions'] = NULL;
|
||||
$this->criteria['offset'] = NULL;
|
||||
|
@ -170,7 +169,9 @@ class uiSearch
|
|||
$this->criteria['filetype'] = UI_SIMPLESEARCH_FILETYPE;
|
||||
$this->criteria['limit'] = UI_SIMPLESEARCH_LIMIT;
|
||||
$this->criteria['counter'] = UI_SIMPLESEARCH_ROWS;
|
||||
$this->criteria['form']['operator'] = 'OR'; ## $criteria['form'] is used for retransfer to form ##
|
||||
|
||||
// $criteria['form'] is used for retransfer to form
|
||||
$this->criteria['form']['operator'] = 'OR';
|
||||
$this->criteria['form']['filetype'] = UI_SIMPLESEARCH_FILETYPE;
|
||||
$this->criteria['form']['limit'] = UI_SIMPLESEARCH_LIMIT;
|
||||
|
||||
|
|
|
@ -87,39 +87,41 @@ class DataEngine {
|
|||
'prefix'=>"like '%s%%'", '<'=>"< '%s'", '='=>"= '%s'",
|
||||
'>'=>"> '%s'", '<='=>"<= '%s'", '>='=>">= '%s'"
|
||||
);
|
||||
$whereArr = array();
|
||||
$whereArr = array();
|
||||
if (is_array($conditions)) {
|
||||
foreach ($conditions as $cond) {
|
||||
$catQn = $cond['cat'];
|
||||
$op = strtolower($cond['op']);
|
||||
$value = strtolower($cond['val']);
|
||||
$splittedQn = XML_Util::splitQualifiedName($catQn);
|
||||
$catNs = $splittedQn['namespace'];
|
||||
$cat = $splittedQn['localPart'];
|
||||
$opVal = sprintf($ops[$op], pg_escape_string($value));
|
||||
// retype for timestamp value
|
||||
if ($cat == 'mtime') {
|
||||
switch ($op) {
|
||||
case 'partial':
|
||||
case 'prefix':
|
||||
break;
|
||||
default:
|
||||
$retype = "::timestamp with time zone";
|
||||
$opVal = "$retype $opVal$retype";
|
||||
if (!empty($value)) {
|
||||
$splittedQn = XML_Util::splitQualifiedName($catQn);
|
||||
$catNs = $splittedQn['namespace'];
|
||||
$cat = $splittedQn['localPart'];
|
||||
$opVal = sprintf($ops[$op], pg_escape_string($value));
|
||||
// retype for timestamp value
|
||||
if ($cat == 'mtime') {
|
||||
switch ($op) {
|
||||
case 'partial':
|
||||
case 'prefix':
|
||||
break;
|
||||
default:
|
||||
$retype = "::timestamp with time zone";
|
||||
$opVal = "$retype $opVal$retype";
|
||||
}
|
||||
}
|
||||
// escape % for sprintf in whereArr construction:
|
||||
$cat = str_replace("%", "%%", $cat);
|
||||
$opVal = str_replace("%", "%%", $opVal);
|
||||
$sqlCond =
|
||||
" %s.predicate = '{$cat}' AND".
|
||||
" %s.objns='_L' AND %s.predxml='T'".
|
||||
" AND lower(%s.object) {$opVal}\n";
|
||||
if (!is_null($catNs)) {
|
||||
$catNs = str_replace("%", "%%", $catNs);
|
||||
$sqlCond = " %s.predns = '{$catNs}' AND $sqlCond";
|
||||
}
|
||||
$whereArr[] = $sqlCond;
|
||||
}
|
||||
// escape % for sprintf in whereArr construction:
|
||||
$cat = str_replace("%", "%%", $cat);
|
||||
$opVal = str_replace("%", "%%", $opVal);
|
||||
$sqlCond =
|
||||
" %s.predicate = '{$cat}' AND".
|
||||
" %s.objns='_L' AND %s.predxml='T'".
|
||||
" AND lower(%s.object) {$opVal}\n";
|
||||
if (!is_null($catNs)) {
|
||||
$catNs = str_replace("%", "%%", $catNs);
|
||||
$sqlCond = " %s.predns = '{$catNs}' AND $sqlCond";
|
||||
}
|
||||
$whereArr[] = $sqlCond;
|
||||
}
|
||||
}
|
||||
return $whereArr;
|
||||
|
@ -209,33 +211,33 @@ class DataEngine {
|
|||
foreach ($whereArr as $i => $v) {
|
||||
$whereArr[$i] = sprintf($v, "md$i", "md$i", "md$i", "md$i", "md$i");
|
||||
$isectBlocks[] =
|
||||
" SELECT gunid FROM ".$CC_CONFIG['mdataTable']." md$i\n".
|
||||
" WHERE\n {$whereArr[$i]}";
|
||||
" SELECT gunid FROM ".$CC_CONFIG['mdataTable']." md$i \n".
|
||||
" WHERE {$whereArr[$i]}";
|
||||
}
|
||||
// query construcion:
|
||||
if (count($isectBlocks)>0) {
|
||||
if (count($isectBlocks) > 0) {
|
||||
$isectBlock =
|
||||
"FROM\n(\n".join("INTERSECT\n", $isectBlocks).") sq\n".
|
||||
"INNER JOIN ".$CC_CONFIG['filesTable']." f ON f.gunid = sq.gunid";
|
||||
"FROM (".join("INTERSECT\n", $isectBlocks).") sq \n".
|
||||
" INNER JOIN ".$CC_CONFIG['filesTable']." f ON f.gunid = sq.gunid";
|
||||
} else {
|
||||
$isectBlock = "FROM ".$CC_CONFIG['filesTable']." f";
|
||||
$isectBlock = "FROM ".$CC_CONFIG['filesTable']." f \n";
|
||||
}
|
||||
$sql = "SELECT $fldsPart\n".$isectBlock;
|
||||
$sql = "SELECT $fldsPart ".$isectBlock;
|
||||
if ($browse) {
|
||||
$sql .= "\nINNER JOIN ".$CC_CONFIG['mdataTable']." br ON br.gunid = f.gunid\n".
|
||||
"WHERE br.objns='_L' AND br.predxml='T' AND br.predicate='{$brFld}'";
|
||||
$sql .= " INNER JOIN ".$CC_CONFIG['mdataTable']." br ON br.gunid = f.gunid \n".
|
||||
" WHERE br.objns='_L' AND br.predxml='T' AND br.predicate='{$brFld}'";
|
||||
if (!is_null($brFldNs)) {
|
||||
$sql .= " AND br.predns='{$brFldNs}'";
|
||||
}
|
||||
$glue = " AND";
|
||||
} else {
|
||||
$glue = "WHERE";
|
||||
$glue = " WHERE ";
|
||||
}
|
||||
if (!is_null($fileCond)) {
|
||||
$sql .= "\n$glue $fileCond";
|
||||
$sql .= " $glue $fileCond";
|
||||
}
|
||||
if ($browse) {
|
||||
$sql .= "\nORDER BY br.object";
|
||||
$sql .= " ORDER BY br.object";
|
||||
}
|
||||
return $sql;
|
||||
}
|
||||
|
@ -326,10 +328,6 @@ class DataEngine {
|
|||
* Limit for result arrays (0 means unlimited)
|
||||
* @param int $offset
|
||||
* Starting point (0 means without offset)
|
||||
* @param string $brFldNs
|
||||
* Namespace prefix of category for browse
|
||||
* @param string $brFld
|
||||
* Metadata category identifier for browse
|
||||
* @return array
|
||||
* arrays of hashes, fields:
|
||||
* cnt : integer - number of matching gunids
|
||||
|
@ -344,10 +342,11 @@ class DataEngine {
|
|||
* OR (in browse mode)
|
||||
* results: array of strings - browsed values
|
||||
*/
|
||||
private function _localGenSearch($criteria, $limit=0, $offset=0,
|
||||
$brFldNs=NULL, $brFld=NULL)
|
||||
private function _localGenSearch($criteria, $limit=0, $offset=0)
|
||||
{
|
||||
global $CC_CONFIG, $CC_DBC;
|
||||
|
||||
// Input values
|
||||
$filetype = (isset($criteria['filetype']) ? $criteria['filetype'] : 'all');
|
||||
$filetype = strtolower($filetype);
|
||||
if (!array_key_exists($filetype, $this->filetypes)) {
|
||||
|
@ -359,71 +358,108 @@ class DataEngine {
|
|||
$operator = (isset($criteria['operator']) ? $criteria['operator'] : 'and');
|
||||
$operator = strtolower($operator);
|
||||
$conditions = (isset($criteria['conditions']) ? $criteria['conditions'] : array());
|
||||
|
||||
// Create the WHERE clause - this is the actual search part
|
||||
$whereArr = $this->_makeWhereArr($conditions);
|
||||
|
||||
// Metadata values to fetch
|
||||
$metadataNames = array('dc:creator', 'dc:source', 'ls:track_num', 'dc:title', 'dcterms:extent');
|
||||
|
||||
// Order by clause
|
||||
$orderby = TRUE;
|
||||
if ((!isset($criteria['orderby']))
|
||||
|| (is_array($criteria['orderby']) && (count($criteria['orderby'])==0))) {
|
||||
// default ORDER BY
|
||||
$orderbyQns = array('dc:creator', 'dc:source', 'dc:title');
|
||||
$orderbyQns = array('dc:creator', 'dc:source', 'ls:track_num', 'dc:title');
|
||||
} else {
|
||||
$orderbyQns = $criteria['orderby'];
|
||||
}
|
||||
if (!is_array($orderbyQns)) {
|
||||
$orderbyQns = array($orderbyQns);
|
||||
}
|
||||
|
||||
$descA = (isset($criteria['desc']) ? $criteria['desc'] : NULL);
|
||||
if (!is_array($descA)) {
|
||||
$descA = array($descA);
|
||||
}
|
||||
$orderJoinSql = array();
|
||||
|
||||
// This section of code adds the metadata values to the results.
|
||||
// Each metadata value is LEFT JOINED to the results, and has the
|
||||
// name of its qualified name with ":" replaced with "_".
|
||||
// Here we also make the ORDER BY clause.
|
||||
$metadataJoinSql = array();
|
||||
$orderBySql = array();
|
||||
foreach ($orderbyQns as $j => $orderbyQn) {
|
||||
// $dataName contains the names of the metadata columns we want to
|
||||
// fetch. It is indexed numerically starting from 1, and the value
|
||||
// in the array is the qualified name with ":" replaced with "_".
|
||||
// e.g. "dc:creator" becomes "dc_creator".
|
||||
$dataName = array();
|
||||
foreach ($metadataNames as $j => $qname) {
|
||||
$i = $j + 1;
|
||||
$obSplitQn = XML_Util::splitQualifiedName($orderbyQn);
|
||||
$obSplitQn = XML_Util::splitQualifiedName($qname);
|
||||
$obNs = $obSplitQn['namespace'];
|
||||
$obLp = $obSplitQn['localPart'];
|
||||
$desc = (isset($descA[$j]) ? $descA[$j] : NULL);
|
||||
$retype = ($obLp == 'mtime' ? '::timestamp with time zone' : '' );
|
||||
$orderJoinSql[] =
|
||||
$metadataJoinSql[] =
|
||||
"LEFT JOIN ".$CC_CONFIG['mdataTable']." m$i\n".
|
||||
" ON m$i.gunid = sq2.gunid AND m$i.predicate='$obLp'".
|
||||
" AND m$i.objns='_L' AND m$i.predxml='T'".
|
||||
(!is_null($obNs)? " AND m$i.predns='$obNs'":'');
|
||||
$orderBySql[] =
|
||||
"m$i.object".$retype.($desc? ' DESC':'');
|
||||
}
|
||||
$browse = !is_null($brFld);
|
||||
if (!$browse) {
|
||||
if (!$orderby) {
|
||||
$fldsPart = "DISTINCT to_hex(f.gunid)as gunid, f.ftype, f.id";
|
||||
} else {
|
||||
$fldsPart = "DISTINCT f.gunid, f.ftype, f.id";
|
||||
|
||||
$dataName[$qname] = str_replace(":", "_", $qname);
|
||||
if (in_array($qname, $orderbyQns)) {
|
||||
$orderBySql[] = $dataName[$qname].$retype.($desc? ' DESC':'');
|
||||
}
|
||||
} else {
|
||||
$fldsPart = "DISTINCT br.object as txt";
|
||||
}
|
||||
$limitPart = ($limit != 0 ? " LIMIT $limit" : '' ).
|
||||
($offset != 0 ? " OFFSET $offset" : '' );
|
||||
|
||||
if (!$orderby) {
|
||||
$fldsPart = "DISTINCT to_hex(f.gunid)as gunid, f.ftype, f.id ";
|
||||
} else {
|
||||
$fldsPart = "DISTINCT f.gunid, f.ftype, f.id ";
|
||||
}
|
||||
|
||||
$fileCond = "f.state='ready'";
|
||||
if (!is_null($filetype)) {
|
||||
$fileCond .= " AND f.ftype='$filetype'";
|
||||
}
|
||||
if ($operator == 'and') { // operator: and
|
||||
$sql = $this->_makeAndSql($fldsPart, $whereArr, $fileCond, $browse, $brFldNs, $brFld);
|
||||
} else { // operator: or
|
||||
$sql = $this->_makeOrSql($fldsPart, $whereArr, $fileCond, $browse, $brFldNs, $brFld);
|
||||
if ($operator == 'and') {
|
||||
$sql = $this->_makeAndSql($fldsPart, $whereArr, $fileCond, false);
|
||||
} else {
|
||||
$sql = $this->_makeOrSql($fldsPart, $whereArr, $fileCond, false);
|
||||
}
|
||||
if (!$browse && $orderby) {
|
||||
$sql = "SELECT to_hex(sq2.gunid)as gunid, m1.object, sq2.ftype, sq2.id\n".
|
||||
"FROM (\n$sql\n)sq2\n".
|
||||
join("\n", $orderJoinSql).
|
||||
|
||||
// the actual values to fetch
|
||||
if ($orderby) {
|
||||
$tmpSql = "SELECT to_hex(sq2.gunid)as gunid, sq2.ftype, sq2.id";
|
||||
$i = 1;
|
||||
foreach ($metadataNames as $qname) {
|
||||
// Special case for track number because if we use text
|
||||
// sorting of this value, then 10 comes right after 1.
|
||||
// So we convert track number to an integer for ordering.
|
||||
if ($qname == "ls:track_num") {
|
||||
$tmpSql .= ", CAST(m$i.object as integer) as ls_track_num";
|
||||
} else {
|
||||
$tmpSql .= ", m$i.object as ".$dataName[$qname];
|
||||
}
|
||||
$i++;
|
||||
}
|
||||
|
||||
$tmpSql .= "\nFROM (\n$sql\n)sq2\n".
|
||||
join("\n", $metadataJoinSql).
|
||||
"ORDER BY ".join(",", $orderBySql)."\n";
|
||||
$sql = $tmpSql;
|
||||
}
|
||||
// echo "\n---\n$sql\n---\n";
|
||||
|
||||
// Get the number of results
|
||||
$cnt = $this->_getNumRows($sql);
|
||||
if (PEAR::isError($cnt)) {
|
||||
return $cnt;
|
||||
}
|
||||
|
||||
// Get actual results
|
||||
$limitPart = ($limit != 0 ? " LIMIT $limit" : '' ).
|
||||
($offset != 0 ? " OFFSET $offset" : '' );
|
||||
$res = $CC_DBC->getAll($sql.$limitPart);
|
||||
if (PEAR::isError($res)) {
|
||||
return $res;
|
||||
|
@ -432,26 +468,19 @@ class DataEngine {
|
|||
$res = array();
|
||||
}
|
||||
$eres = array();
|
||||
// echo "\n---\n"; var_dump($res); echo"\n---\n";
|
||||
//$categoryNames = array('dc:title', 'dc:creator', 'dc:source', 'dcterms:extent');
|
||||
foreach ($res as $it) {
|
||||
if (!$browse) {
|
||||
$gunid = StoredFile::NormalizeGunid($it['gunid']);
|
||||
//$values = $this->gb->bsGetMetadataValue($it['id'], $categoryNames);
|
||||
$values = $this->gb->bsGetMetadataValue($it['id']);
|
||||
$eres[] = array(
|
||||
'id' => $it['id'],
|
||||
'gunid' => $gunid,
|
||||
'type' => $it['ftype'],
|
||||
'title' => $values['dc:title']["object"],
|
||||
'creator' => (isset($values['dc:creator']) ? $values['dc:creator']["object"] : NULL ),
|
||||
'duration' => $values['dcterms:extent']["object"],
|
||||
'length' => $values['dcterms:extent']["object"],
|
||||
'source' => (isset($values['dc:source']) ? $values['dc:source']["object"] : NULL ),
|
||||
);
|
||||
} else {
|
||||
$eres[] = $it['txt'];
|
||||
}
|
||||
$gunid = StoredFile::NormalizeGunid($it['gunid']);
|
||||
$eres[] = array(
|
||||
'id' => $it['id'],
|
||||
'gunid' => $gunid,
|
||||
'type' => strtolower($it['ftype']),
|
||||
'title' => $it['dc_title'],
|
||||
'creator' => $it['dc_creator'],
|
||||
'duration' => $it['dcterms_extent'],
|
||||
'length' => $it['dcterms_extent'],
|
||||
'source' => $it['dc_source'],
|
||||
'track_num' => $it['ls_track_num'],
|
||||
);
|
||||
}
|
||||
return array('results'=>$eres, 'cnt'=>$cnt);
|
||||
}
|
||||
|
@ -461,7 +490,8 @@ class DataEngine {
|
|||
* Return values of specified metadata category
|
||||
*
|
||||
* @param string $category
|
||||
* metadata category name, with or without namespace prefix (dc:title, author)
|
||||
* metadata category name, with or without namespace prefix
|
||||
* (dc:title, author)
|
||||
* @param int $limit
|
||||
* limit for result arrays (0 means unlimited)
|
||||
* @param int $offset
|
||||
|
@ -480,7 +510,7 @@ class DataEngine {
|
|||
$catNs = $r['namespace'];
|
||||
$cat = $r['localPart'];
|
||||
if (is_array($criteria) && count($criteria) > 0) {
|
||||
return $this->_localGenSearch($criteria, $limit, $offset, $catNs, $cat);
|
||||
return $this->_browseCategory($criteria, $limit, $offset, $catNs, $cat);
|
||||
}
|
||||
$sqlCond = "m.predicate='$cat' AND m.objns='_L' AND m.predxml='T'";
|
||||
if (!is_null($catNs)) {
|
||||
|
@ -491,7 +521,6 @@ class DataEngine {
|
|||
$sql =
|
||||
"SELECT DISTINCT m.object FROM ".$CC_CONFIG['mdataTable']." m\n".
|
||||
"WHERE $sqlCond";
|
||||
// echo "\n---\n$sql\n---\n";
|
||||
$cnt = $this->_getNumRows($sql);
|
||||
if (PEAR::isError($cnt)) {
|
||||
return $cnt;
|
||||
|
@ -507,6 +536,74 @@ class DataEngine {
|
|||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetching the list of metadata values for a particular category.
|
||||
*
|
||||
* @param array $criteria
|
||||
* @param int $limit
|
||||
* @param int $offset
|
||||
* @param string $brFldNs
|
||||
* Namespace prefix of category for browse
|
||||
* @param string $brFld
|
||||
* Metadata category identifier for browse.
|
||||
* @return array|PEAR_Error
|
||||
*/
|
||||
private function _browseCategory($criteria, $limit=0, $offset=0,
|
||||
$brFldNs=NULL, $brFld=NULL)
|
||||
{
|
||||
global $CC_CONFIG, $CC_DBC;
|
||||
|
||||
// Input values
|
||||
$filetype = (isset($criteria['filetype']) ? $criteria['filetype'] : 'all');
|
||||
$filetype = strtolower($filetype);
|
||||
if (!array_key_exists($filetype, $this->filetypes)) {
|
||||
return PEAR::raiseError(
|
||||
'DataEngine::_browseCategory: unknown filetype in search criteria'
|
||||
);
|
||||
}
|
||||
$filetype = $this->filetypes[$filetype];
|
||||
$operator = (isset($criteria['operator']) ? $criteria['operator'] : 'and');
|
||||
$operator = strtolower($operator);
|
||||
$conditions = (isset($criteria['conditions']) ? $criteria['conditions'] : array());
|
||||
|
||||
// Create the WHERE clause - this is the actual search part
|
||||
$whereArr = $this->_makeWhereArr($conditions);
|
||||
|
||||
$fldsPart = "DISTINCT br.object as txt";
|
||||
$fileCond = "f.state='ready'";
|
||||
if (!is_null($filetype)) {
|
||||
$fileCond .= " AND f.ftype='$filetype'";
|
||||
}
|
||||
if ($operator == 'and') {
|
||||
$sql = $this->_makeAndSql($fldsPart, $whereArr, $fileCond, true, $brFldNs, $brFld);
|
||||
} else {
|
||||
$sql = $this->_makeOrSql($fldsPart, $whereArr, $fileCond, true, $brFldNs, $brFld);
|
||||
}
|
||||
|
||||
// Get the number of results
|
||||
$cnt = $this->_getNumRows($sql);
|
||||
if (PEAR::isError($cnt)) {
|
||||
return $cnt;
|
||||
}
|
||||
|
||||
// Get actual results
|
||||
$limitPart = ($limit != 0 ? " LIMIT $limit" : '' ).
|
||||
($offset != 0 ? " OFFSET $offset" : '' );
|
||||
$res = $CC_DBC->getAll($sql.$limitPart);
|
||||
if (PEAR::isError($res)) {
|
||||
return $res;
|
||||
}
|
||||
if (!is_array($res)) {
|
||||
$res = array();
|
||||
}
|
||||
$eres = array();
|
||||
foreach ($res as $it) {
|
||||
$eres[] = $it['txt'];
|
||||
}
|
||||
return array('results'=>$eres, 'cnt'=>$cnt);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get number of rows in query result
|
||||
*
|
||||
|
|
|
@ -511,7 +511,7 @@ class GreenBox extends BasicStor {
|
|||
* cnt : integer - number of matching values
|
||||
* @see BasicStor::bsBrowseCategory
|
||||
*/
|
||||
public function browseCategory($category, $criteria, $sessid = '')
|
||||
public function browseCategory($category, $criteria = null, $sessid = '')
|
||||
{
|
||||
$limit = 0;
|
||||
$offset = 0;
|
||||
|
|
Loading…
Reference in New Issue