/**
  * Prepopulate record fields according to rules in prepopulate.conf
  *
  * @param array $pa_options Options array. Available options are:
  * 		prepopulateConfig = override path to prepopulate.conf, e.g. for testing purposes
  * @return bool success or not
  */
 public function prepopulateFields($pa_options = null)
 {
     if (!$this->getPrimaryKey()) {
         return false;
     }
     if (!($vs_prepopulate_cfg = caGetOption('prepopulateConfig', $pa_options, null))) {
         $vs_prepopulate_cfg = $this->getAppConfig()->get('prepopulate_config');
     }
     $o_prepopulate_conf = Configuration::load($vs_prepopulate_cfg);
     if (!($o_prepopulate_conf->get('prepopulate_fields_on_save') || $o_prepopulate_conf->get('prepopulate_fields_on_load'))) {
         return false;
     }
     $va_rules = $o_prepopulate_conf->get('prepopulate_rules');
     if (!$va_rules || !is_array($va_rules) || sizeof($va_rules) < 1) {
         return false;
     }
     global $g_ui_locale_id;
     // we need to unset the form timestamp to disable the 'Changes have been made since you loaded this data' warning when we update() $this
     // the warning makes sense because an update()/insert() is called before we arrive here but after the form_timestamp ... but we chose to ignore it
     $vn_timestamp = $_REQUEST['form_timestamp'];
     unset($_REQUEST['form_timestamp']);
     $vb_we_set_transaction = true;
     if (!$this->inTransaction()) {
         $this->setTransaction(new Transaction($this->getDb()));
         $vb_we_set_transaction = true;
     }
     // process rules
     $va_expression_vars = array();
     // we only process those if and when we need them
     foreach ($va_rules as $vs_rule_key => $va_rule) {
         if ($this->tableName() != $va_rule['table']) {
             continue;
         }
         // check target
         $vs_target = $va_rule['target'];
         if (strlen($vs_target) < 1) {
             Debug::msg("[prepopulateFields()] skipping rule {$vs_rule_key} because target is not set");
             continue;
         }
         // check template
         $vs_template = $va_rule['template'];
         if (strlen($vs_template) < 1) {
             Debug::msg("[prepopulateFields()] skipping rule {$vs_rule_key} because template is not set");
             continue;
         }
         $vs_mode = caGetOption('mode', $va_rule, 'merge');
         // respect restrictToTypes option
         if ($va_rule['restrictToTypes'] && is_array($va_rule['restrictToTypes']) && sizeof($va_rule['restrictToTypes']) > 0) {
             if (!in_array($this->getTypeCode(), $va_rule['restrictToTypes'])) {
                 Debug::msg("[prepopulateFields()] skipping rule {$vs_rule_key} because current record type " . $this->getTypeCode() . " is not in restrictToTypes");
                 continue;
             }
         }
         // skip this rule if expression is true
         if ($va_rule['skipIfExpression'] && strlen($va_rule['skipIfExpression']) > 0) {
             $va_tags = caGetTemplateTags($va_rule['skipIfExpression']);
             foreach ($va_tags as $vs_tag) {
                 if (!isset($va_expression_vars[$vs_tag])) {
                     $va_expression_vars[$vs_tag] = $this->get($vs_tag, array('returnIdno' => true, 'delimiter' => ';'));
                 }
             }
             if (ExpressionParser::evaluate($va_rule['skipIfExpression'], $va_expression_vars)) {
                 Debug::msg("[prepopulateFields()] skipping rule {$vs_rule_key} because skipIfExpression evaluated true");
                 continue;
             }
         }
         // evaluate template
         $vs_value = caProcessTemplateForIDs($vs_template, $this->tableNum(), array($this->getPrimaryKey()), array('path' => true));
         Debug::msg("[prepopulateFields()] processed template for rule {$vs_rule_key} value is: " . $vs_value);
         // inject into target
         $va_parts = explode('.', $vs_target);
         // intrinsic or simple (non-container) attribute
         if (sizeof($va_parts) == 2) {
             // intrinsic
             if ($this->hasField($va_parts[1])) {
                 switch (strtolower($vs_mode)) {
                     case 'overwrite':
                         // always set
                         $this->set($va_parts[1], $vs_value);
                         break;
                     case 'addifempty':
                     default:
                         if (!$this->get($va_parts[1])) {
                             $this->set($va_parts[1], $vs_value);
                         } else {
                             Debug::msg("[prepopulateFields()] rule {$vs_rule_key}: intrinsic skipped because it already has value and mode is addIfEmpty or merge");
                         }
                         break;
                 }
                 // attribute/element
             } elseif ($this->hasElement($va_parts[1])) {
                 $va_attributes = $this->getAttributesByElement($va_parts[1]);
                 if (sizeof($va_attributes) > 1) {
                     Debug::msg("[prepopulateFields()] containers with multiple values are not supported");
                     continue;
                 }
                 switch (strtolower($vs_mode)) {
                     case 'overwrite':
                         // always replace first value we find
                         $this->replaceAttribute(array($va_parts[1] => $vs_value, 'locale_id' => $g_ui_locale_id), $va_parts[1]);
                         break;
                     default:
                     case 'addifempty':
                         // only add value if none exists
                         if (!$this->get($vs_target)) {
                             $this->replaceAttribute(array($va_parts[1] => $vs_value, 'locale_id' => $g_ui_locale_id), $va_parts[1]);
                         }
                         break;
                 }
             }
             // "container"
         } elseif (sizeof($va_parts) == 3) {
             // actual container
             if ($this->hasElement($va_parts[1])) {
                 $va_attr = $this->getAttributesByElement($va_parts[1]);
                 switch (sizeof($va_attr)) {
                     case 1:
                         switch (strtolower($vs_mode)) {
                             case 'overwrite':
                                 $vo_attr = array_pop($va_attr);
                                 $va_value = array($va_parts[2] => $vs_value);
                                 foreach ($vo_attr->getValues() as $o_val) {
                                     if ($o_val->getElementCode() != $va_parts[2]) {
                                         $va_value[$o_val->getElementCode()] = $o_val->getDisplayValue();
                                     }
                                 }
                                 $this->_editAttribute($vo_attr->getAttributeID(), $va_value);
                                 break;
                             case 'addifempty':
                                 $vo_attr = array_pop($va_attr);
                                 $va_value = array($va_parts[2] => $vs_value);
                                 $vb_update = false;
                                 foreach ($vo_attr->getValues() as $o_val) {
                                     if ($o_val->getElementCode() != $va_parts[2]) {
                                         $va_value[$o_val->getElementCode()] = $o_val->getDisplayValue();
                                     } else {
                                         if (!$o_val->getDisplayValue()) {
                                             $vb_update = true;
                                         }
                                     }
                                 }
                                 if ($vb_update) {
                                     $this->editAttribute($vo_attr->getAttributeID(), $va_parts[1], $va_value);
                                 }
                                 break;
                             default:
                                 Debug::msg("[prepopulateFields()] unsupported mode {$vs_mode} for target bundle");
                                 break;
                         }
                         break;
                     case 0:
                         // if no container value exists, always add it (ignoring mode)
                         $this->addAttribute(array($va_parts[2] => $vs_value, 'locale_id' => $g_ui_locale_id), $va_parts[1]);
                         break;
                     default:
                         Debug::msg("[prepopulateFields()] containers with multiple values are not supported");
                         break;
                 }
                 // labels
             } elseif ($va_parts[1] == 'preferred_labels' || $va_parts[1] == 'nonpreferred_labels') {
                 $vb_preferred = $va_parts[1] == 'preferred_labels';
                 if (!($t_label = $this->getAppDatamodel()->getInstanceByTableName($this->getLabelTableName(), true))) {
                     continue;
                 }
                 if (!$t_label->hasField($va_parts[2])) {
                     continue;
                 }
                 switch ($this->getLabelCount($vb_preferred)) {
                     case 0:
                         // if no value exists, always add it (ignoring mode)
                         $this->addLabel(array($va_parts[2] => $vs_value), $g_ui_locale_id, null, $vb_preferred);
                         break;
                     case 1:
                         switch (strtolower($vs_mode)) {
                             case 'overwrite':
                             case 'addifempty':
                                 $va_labels = $this->getLabels(null, $vb_preferred ? __CA_LABEL_TYPE_PREFERRED__ : __CA_LABEL_TYPE_NONPREFERRED__);
                                 if (sizeof($va_labels)) {
                                     $va_labels = caExtractValuesByUserLocale($va_labels);
                                     $va_label = array_shift($va_labels);
                                     $va_label = $va_label[0];
                                     $va_label[$va_parts[2]] = $vs_value;
                                     $vb_update = false;
                                     if (strtolower($vs_mode) == 'overwrite') {
                                         $va_label[$va_parts[2]] = $vs_value;
                                         $vb_update = true;
                                     } else {
                                         if (strlen(trim($va_label[$va_parts[2]])) == 0) {
                                             // in addifempty mode only edit label when field is not set
                                             $va_label[$va_parts[2]] = $vs_value;
                                             $vb_update = true;
                                         }
                                     }
                                     if ($vb_update) {
                                         $this->editLabel($va_label['label_id'], $va_label, $g_ui_locale_id, null, $vb_preferred);
                                     }
                                 } else {
                                     $this->addLabel(array($va_parts[2] => $vs_value), $g_ui_locale_id, null, $vb_preferred);
                                 }
                                 break;
                             default:
                                 Debug::msg("[prepopulateFields()] unsupported mode {$vs_mode} for target bundle");
                                 break;
                         }
                         break;
                     default:
                         Debug::msg("[prepopulateFields()] records with multiple labels are not supported");
                         break;
                 }
             }
         }
     }
     $vn_old_mode = $this->getMode();
     $this->setMode(ACCESS_WRITE);
     $this->update();
     $this->setMode($vn_old_mode);
     $_REQUEST['form_timestamp'] = $vn_timestamp;
     if ($this->numErrors() > 0) {
         foreach ($this->getErrors() as $vs_error) {
             Debug::msg("[prepopulateFields()] there was an error while updating the record: " . $vs_error);
         }
         if ($vb_we_set_transaction) {
             $this->removeTransaction(false);
         }
         return false;
     }
     if ($vb_we_set_transaction) {
         $this->removeTransaction(true);
     }
     return true;
 }
コード例 #2
0
 function getMenu($menu_id)
 {
     if ($menu_id == null) {
         Debug::msg('Error', __FILE__, __LINE__);
         return;
     }
     $arrSubmenus = $this->SelectOrder('mm_menu_submenu', 'submenu_id', 'orden', "menu_id = {$menu_id}");
     if ($this->hasError() || count($arrSubmenus) == 0 || $arrSubmenus[0]['mm_menu_submenu.submenu_id'] == null) {
         return null;
     }
     for ($i = 0; $i < count($arrSubmenus); $i++) {
         $submenu_id = $arrSubmenus[$i]['mm_menu_submenu.submenu_id'];
         $aux = $this->Select('mm_submenu', 'name', "submenu_id = {$submenu_id}");
         $ret_val[$i]['name'] = $aux[0]['mm_submenu.name'];
         $ret_val[$i]['submenu_id'] = $arrSubmenus[$i]['mm_menu_submenu.submenu_id'];
         $arrOptions = $this->getSubmenu($arrSubmenus[$i]['mm_menu_submenu.submenu_id']);
         for ($j = 0; $j < count($arrOptions); $j++) {
             $ret_val[$i][$j]['name'] = $arrOptions[$j]['name'];
             $ret_val[$i][$j]['param'] = $arrOptions[$j]['param'];
             $ret_val[$i][$j]['option_id'] = $arrOptions[$j]['option_id'];
             $ret_val[$i][$j]['module_name'] = $arrOptions[$j]['module_name'];
         }
     }
     return $ret_val;
 }
コード例 #3
0
ファイル: SearchEngine.php プロジェクト: kai-iak/pawtucket2
 /**
  * Performs a search by calling the search() method on the underlying search engine plugin
  * Information about all searches is logged to ca_search_log
  *
  * @param string $ps_search The search to perform; engine takes Lucene syntax query
  * @param SearchResult $po_result  A newly instantiated sub-class of SearchResult to place search results into and return. If this is not set, then a generic SearchResults object will be returned.
  * @param array $pa_options Optional array of options for the search. Options include:
  *
  *		sort = field or attribute to sort on in <table name>.<field or attribute name> format (eg. ca_objects.idno); default is to sort on relevance (aka. sort='_natural')
  *		sortDirection = direction to sort results by, either 'asc' for ascending order or 'desc' for descending order; default is 'asc'
  *		no_cache = if true, search is performed regardless of whether results for the search are already cached; default is false
  *		limit = if set then search results will be limited to the quantity specified. If not set then all results are returned.
  *		form_id = optional form identifier string to record in log for search
  *		log_details = optional form description to record in log for search
  *		search_source = optional source indicator text to record in log for search
  *		checkAccess = optional array of access values to filter results on
  *		showDeleted = if set to true, related items that have been deleted are returned. Default is false.
  *		deletedOnly = if set to true, only deleted items are returned. Default is false.
  *		limitToModifiedOn = if set returned results will be limited to rows modified within the specified date range. The value should be a date/time expression parse-able by TimeExpressionParser
  *		sets = if value is a list of set_ids, only rows that are members of those sets will be returned
  *		user_id = If set item level access control is performed relative to specified user_id, otherwise defaults to logged in user
  *		dontFilterByACL = if true ACL checking is not performed on results
  *		appendToSearch = 
  *		restrictSearchToFields = 
  *
  * @return SearchResult Results packages in a SearchResult object, or sub-class of SearchResult if an instance was passed in $po_result
  * @uses TimeExpressionParser::parse
  */
 public function doSearch($ps_search, $po_result = null, $pa_options = null)
 {
     $t = new Timer();
     global $AUTH_CURRENT_USER_ID;
     if ($vs_append_to_search = isset($pa_options['appendToSearch']) ? ' ' . $pa_options['appendToSearch'] : '') {
         $ps_search .= $vs_append_to_search;
     }
     $ps_search = str_replace("[BLANK]", '"[BLANK]"', $ps_search);
     // the special [BLANK] search term, which returns records that have *no* content in a specific fields, has to be quoted in order to protect the square brackets from the parser.
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     if (($vn_limit = caGetOption('limit', $pa_options, null, array('castTo' => 'int'))) < 0) {
         $vn_limit = null;
     }
     $vs_sort = caGetOption('sort', $pa_options, null);
     $vs_sort_direction = strtolower(caGetOption('sortDirection', $pa_options, caGetOption('sort_direction', $pa_options, null)));
     //print "QUERY=$ps_search<br>";
     //
     // Note that this is *not* misplaced code that should be in the Lucene plugin!
     //
     // We are using the Lucene syntax as our query syntax regardless the of back-end search engine.
     // The Lucene calls below just parse the query and then rewrite access points as-needed; the result
     // is a Lucene-compliant query ready-to-roll that is passed to the engine plugin. Of course, the Lucene
     // plugin just uses the string as-is... other plugins my choose to parse it however they wish to.
     //
     //
     // Process suffixes list... if search conforms to regex then we append a suffix.
     // This is useful, for example, to allow auto-wildcarding of accession numbers: if the search looks like an accession regex-wise we can append a "*"
     //
     $va_suffixes = $this->opo_search_config->getAssoc('search_suffixes');
     if (is_array($va_suffixes) && sizeof($va_suffixes) && !preg_match('!"!', $ps_search)) {
         // don't add suffix wildcards when quoting
         foreach ($va_suffixes as $vs_preg => $vs_suffix) {
             if (preg_match("!{$vs_preg}!", $ps_search)) {
                 $ps_search = preg_replace("!({$vs_preg})[\\*]*!", "\$1{$vs_suffix}", $ps_search);
             }
         }
     }
     $vb_no_cache = isset($pa_options['no_cache']) ? $pa_options['no_cache'] : false;
     unset($pa_options['no_cache']);
     $vn_cache_timeout = (int) $this->opo_search_config->get('cache_timeout');
     if ($vn_cache_timeout == 0) {
         $vb_no_cache = true;
     }
     // don't try to cache if cache timeout is 0 (0 means disabled)
     $t_table = $this->opo_datamodel->getInstanceByTableName($this->ops_tablename, true);
     $vs_cache_key = md5($ps_search . "/" . print_R($this->getTypeRestrictionList(), true));
     $o_cache = new SearchCache();
     $vb_from_cache = false;
     if (!$vb_no_cache && $o_cache->load($vs_cache_key, $this->opn_tablenum, $pa_options)) {
         $vn_created_on = $o_cache->getParameter('created_on');
         if (time() - $vn_created_on < $vn_cache_timeout) {
             Debug::msg('SEARCH cache hit for ' . $vs_cache_key);
             $va_hits = $o_cache->getResults();
             if ($vs_sort != '_natural') {
                 $va_hits = $this->sortHits($va_hits, $this->ops_tablename, $vs_sort, $vs_sort_direction);
             } elseif ($vs_sort == '_natural' && $vs_sort_direction == 'desc') {
                 $va_hits = array_reverse($va_hits);
             }
             $o_res = new WLPlugSearchEngineCachedResult($va_hits, $this->opn_tablenum);
             $vb_from_cache = true;
         } else {
             Debug::msg('cache expire for ' . $vs_cache_key);
             $o_cache->remove();
         }
     }
     if (!$vb_from_cache) {
         Debug::msg('SEARCH cache miss for ' . $vs_cache_key);
         $vs_char_set = $this->opo_app_config->get('character_set');
         $o_query_parser = new LuceneSyntaxParser();
         $o_query_parser->setEncoding($vs_char_set);
         $o_query_parser->setDefaultOperator(LuceneSyntaxParser::B_AND);
         $ps_search = preg_replace('![\']+!', '', $ps_search);
         try {
             $o_parsed_query = $o_query_parser->parse($ps_search, $vs_char_set);
         } catch (Exception $e) {
             // Retry search with all non-alphanumeric characters removed
             try {
                 $o_parsed_query = $o_query_parser->parse(preg_replace("![^A-Za-z0-9 ]+!", " ", $ps_search), $vs_char_set);
             } catch (Exception $e) {
                 $o_parsed_query = $o_query_parser->parse("", $vs_char_set);
             }
         }
         $va_rewrite_results = $this->_rewriteQuery($o_parsed_query);
         $o_rewritten_query = new Zend_Search_Lucene_Search_Query_Boolean($va_rewrite_results['terms'], $va_rewrite_results['signs']);
         $vs_search = $this->_queryToString($o_rewritten_query);
         //print "<div style='background:#FFFFFF; padding: 5px; border: 1px dotted #666666;'><strong>DEBUG: </strong>".$ps_search.'/'.$vs_search."</div>";
         // Filter deleted records out of final result
         if (isset($pa_options['deletedOnly']) && $pa_options['deletedOnly'] && $t_table->hasField('deleted')) {
             $this->addResultFilter($this->ops_tablename . '.deleted', '=', '1');
         } else {
             if ((!isset($pa_options['showDeleted']) || !$pa_options['showDeleted']) && $t_table->hasField('deleted')) {
                 $this->addResultFilter($this->ops_tablename . '.deleted', '=', '0');
             }
         }
         if (isset($pa_options['checkAccess']) && (is_array($pa_options['checkAccess']) && sizeof($pa_options['checkAccess']))) {
             $va_access_values = $pa_options['checkAccess'];
             $this->addResultFilter($this->ops_tablename . '.access', 'IN', join(",", $va_access_values));
         }
         $vb_no_types = false;
         if (is_array($va_type_ids = $this->getTypeRestrictionList()) && sizeof($va_type_ids) > 0) {
             if ($t_table->getFieldInfo('type_id', 'IS_NULL')) {
                 $va_type_ids[] = 'NULL';
             }
             $this->addResultFilter($this->ops_tablename . '.type_id', 'IN', join(",", $va_type_ids));
         } elseif (is_array($va_type_ids) && sizeof($va_type_ids) == 0) {
             $vb_no_types = true;
         }
         if (!$vb_no_types) {
             // Filter on source
             if (is_array($va_source_ids = $this->getSourceRestrictionList())) {
                 $this->addResultFilter($this->ops_tablename . '.source_id', 'IN', join(",", $va_source_ids));
             }
             if (in_array($t_table->getHierarchyType(), array(__CA_HIER_TYPE_SIMPLE_MONO__, __CA_HIER_TYPE_MULTI_MONO__))) {
                 $this->addResultFilter($this->ops_tablename . '.parent_id', 'IS NOT', NULL);
             }
             if (is_array($va_restrict_to_fields = caGetOption('restrictSearchToFields', $pa_options, null)) && $this->opo_engine->can('restrict_to_fields')) {
                 $this->opo_engine->setOption('restrictSearchToFields', $va_restrict_to_fields);
             }
             $o_res = $this->opo_engine->search($this->opn_tablenum, $vs_search, $this->opa_result_filters, $o_rewritten_query);
             // cache the results
             $va_hits = $o_res->getPrimaryKeyValues($vn_limit);
             $o_res->seek(0);
         } else {
             $va_hits = array();
         }
         if (isset($pa_options['sets']) && $pa_options['sets']) {
             $va_hits = $this->filterHitsBySets($va_hits, $pa_options['sets'], array('search' => $vs_search));
         }
         $vn_user_id = isset($pa_options['user_id']) && (int) $pa_options['user_id'] ? (int) $pa_options['user_id'] : (int) $AUTH_CURRENT_USER_ID;
         if ((!isset($pa_options['dontFilterByACL']) || !$pa_options['dontFilterByACL']) && $this->opo_app_config->get('perform_item_level_access_checking') && method_exists($t_table, "supportsACL") && $t_table->supportsACL()) {
             $va_hits = $this->filterHitsByACL($va_hits, $this->opn_tablenum, $vn_user_id, __CA_ACL_READONLY_ACCESS__);
         }
         if ($vs_sort != '_natural') {
             $va_hits = $this->sortHits($va_hits, $t_table->tableName(), $pa_options['sort'], isset($pa_options['sort_direction']) ? $pa_options['sort_direction'] : null);
         } elseif ($vs_sort == '_natural' && $vs_sort_direction == 'desc') {
             $va_hits = array_reverse($va_hits);
         }
         $o_res = new WLPlugSearchEngineCachedResult($va_hits, $this->opn_tablenum);
         // cache for later use
         if (!$vb_no_cache) {
             $o_cache->save($vs_cache_key, $this->opn_tablenum, $va_hits, array('created_on' => time()), null, $pa_options);
         }
         // log search
         $o_log = new Searchlog();
         $vn_search_form_id = isset($pa_options['form_id']) ? $pa_options['form_id'] : null;
         $vs_log_details = isset($pa_options['log_details']) ? $pa_options['log_details'] : '';
         $vs_search_source = isset($pa_options['search_source']) ? $pa_options['search_source'] : '';
         $vn_execution_time = $t->getTime(4);
         $o_log->log(array('user_id' => $vn_user_id, 'table_num' => $this->opn_tablenum, 'search_expression' => $ps_search, 'num_hits' => sizeof($va_hits), 'form_id' => $vn_search_form_id, 'ip_addr' => $_SERVER['REMOTE_ADDR'] ? $_SERVER['REMOTE_ADDR'] : null, 'details' => $vs_log_details, 'search_source' => $vs_search_source, 'execution_time' => $vn_execution_time));
     }
     if ($po_result) {
         $po_result->init($o_res, $this->opa_tables, $pa_options);
         return $po_result;
     } else {
         return new SearchResult($o_res, $this->opa_tables);
     }
 }
コード例 #4
0
 public function getExtraInfo($pa_settings, $ps_url)
 {
     $vs_lang = caGetOption('lang', $pa_settings, 'en');
     // readable version of get parameters
     $va_get_params = array('action' => 'query', 'titles' => self::getPageTitleFromURI($ps_url), 'prop' => 'pageimages|info|extracts', 'inprop' => 'url', 'piprop' => 'name|thumbnail', 'pithumbsize' => '200px', 'format' => 'json');
     $vs_content = caQueryExternalWebservice('https://' . $vs_lang . '.wikipedia.org/w/api.php?' . caConcatGetParams($va_get_params));
     $va_content = @json_decode($vs_content, true);
     if (!is_array($va_content) || !isset($va_content['query']['pages'])) {
         return array();
     }
     // the top two levels are 'query' and 'pages'
     $va_results = $va_content['query']['pages'];
     if (sizeof($va_results) > 1) {
         Debug::msg('[Wikipedia] Found multiple results for page title ' . self::getPageTitleFromURI($ps_url));
     }
     if (sizeof($va_results) == 0) {
         Debug::msg('[Wikipedia] Couldnt find any results for page title ' . self::getPageTitleFromURI($ps_url));
         return null;
     }
     $va_result = array_shift($va_results);
     // try to extract the first paragraph (usually an abstract/summary of the article)
     $vs_abstract = preg_replace("/\\s+<p><\\/p>\\s+<h2>.+\$/ms", "", $va_result['extract']);
     return array('image_thumbnail' => $va_result['thumbnail']['source'], 'image_thumbnail_width' => $va_result['thumbnail']['width'], 'image_thumbnail_height' => $va_result['thumbnail']['height'], 'image_viewer_url' => $va_result['fullurl'] . '#/media/File:' . $va_result['pageimage'], 'title' => $va_result['title'], 'pageid' => $va_result['page_id'], 'fullurl' => $va_result['fullurl'], 'canonicalurl' => $va_result['canonicalurl'], 'extract' => $va_result['extract'], 'abstract' => $vs_abstract);
 }
コード例 #5
0
ファイル: Solr.php プロジェクト: kai-iak/pawtucket2
 public function search($pn_subject_tablenum, $ps_search_expression, $pa_filters = array(), $po_rewritten_query = null)
 {
     $va_solr_search_filters = array();
     $vn_i = 0;
     $va_old_signs = is_object($po_rewritten_query) ? $po_rewritten_query->getSigns() : array();
     $va_terms = $va_signs = array();
     if ($po_rewritten_query) {
         foreach ($po_rewritten_query->getSubqueries() as $o_lucene_query_element) {
             if (!$va_old_signs || !is_array($va_old_signs)) {
                 // if array is null then according to Zend Lucene all subqueries should be "are required"... so we AND them
                 $vs_op = "AND";
             } else {
                 if (is_null($va_old_signs[$vn_i])) {
                     // is the sign for a particular query is null then OR is (it is "neither required nor prohibited")
                     $vs_op = 'OR';
                 } else {
                     $vs_op = $va_old_signs[$vn_i] === false ? 'NOT' : 'AND';
                     // true sign indicated "required" (AND) operation, false indicated "prohibited" (NOT) operation
                 }
             }
             if ($vn_i == 0) {
                 $vs_op = 'OR';
             }
             // advanced search queries are for some reason nested 1-element boolean queries in boolean queries
             if (get_class($o_lucene_query_element) == 'Zend_Search_Lucene_Search_Query_Boolean') {
                 $va_subqueries = $o_lucene_query_element->getSubqueries();
                 if (sizeof($va_subqueries) == 1) {
                     $o_lucene_query_element = array_shift($va_subqueries);
                 }
             }
             switch ($vs_class = get_class($o_lucene_query_element)) {
                 case 'Zend_Search_Lucene_Search_Query_Term':
                 case 'Zend_Search_Lucene_Search_Query_MultiTerm':
                 case 'Zend_Search_Lucene_Search_Query_Phrase':
                     $vs_access_point = '';
                     if ($vs_class != 'Zend_Search_Lucene_Search_Query_Term') {
                         $va_raw_terms = array();
                         foreach ($o_lucene_query_element->getQueryTerms() as $o_term) {
                             if (!$vs_access_point && ($vs_field = $o_term->field)) {
                                 $vs_access_point = $vs_field;
                             }
                             $va_raw_terms[] = $vs_text = (string) $o_term->text;
                         }
                         $vs_term = join(" ", $va_raw_terms);
                     } else {
                         $vs_access_point = $o_lucene_query_element->getTerm()->field;
                         $vs_term = $o_lucene_query_element->getTerm()->text;
                     }
                     if ($vs_access_point) {
                         list($vs_table, $vs_field, $vs_sub_field) = explode('.', $vs_access_point);
                         if (in_array($vs_table, array('created', 'modified'))) {
                             if (!$this->opo_tep->parse($vs_term)) {
                                 break;
                             }
                             $va_range = $this->opo_tep->getUnixTimestamps();
                             $vn_user_id = null;
                             if ($vs_field = trim($vs_field)) {
                                 if (!is_int($vs_field)) {
                                     $t_user = new ca_users();
                                     if ($t_user->load(array("user_name" => $vs_field))) {
                                         $vn_user_id = (int) $t_user->getPrimaryKey();
                                     }
                                 } else {
                                     $vn_user_id = (int) $vs_field;
                                 }
                             }
                             $vs_user_sql = $vn_user_id ? " AND (ccl.user_id = " . (int) $vn_user_id . ")" : "";
                             switch ($vs_table) {
                                 case 'created':
                                     if ($vn_user_id) {
                                         $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Boolean(array(new Zend_Search_Lucene_Index_Term('[' . $this->opo_tep->getText(array('start_as_iso8601' => true)) . " TO " . $this->opo_tep->getText(array('end_as_iso8601' => true)) . ']', 'created'), new Zend_Search_Lucene_Index_Term($vn_user_id, 'created_user_id')), array(true, true));
                                     } else {
                                         $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term('[' . $this->opo_tep->getText(array('start_as_iso8601' => true)) . " TO " . $this->opo_tep->getText(array('end_as_iso8601' => true)) . ']', 'created'));
                                     }
                                     break;
                                 case 'modified':
                                     if ($vn_user_id) {
                                         $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Boolean(array(new Zend_Search_Lucene_Index_Term('[' . $this->opo_tep->getText(array('start_as_iso8601' => true)) . " TO " . $this->opo_tep->getText(array('end_as_iso8601' => true)) . ']', 'modified'), new Zend_Search_Lucene_Index_Term($vn_user_id, 'modified_user_id')), array(true, true));
                                     } else {
                                         $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term('[' . $this->opo_tep->getText(array('start_as_iso8601' => true)) . " TO " . $this->opo_tep->getText(array('end_as_iso8601' => true)) . ']', 'modified'));
                                     }
                                     break;
                             }
                         } else {
                             if ($vs_table && $vs_field) {
                                 $t_table = $this->opo_datamodel->getInstanceByTableName($vs_table, true);
                                 if ($t_table) {
                                     $vs_table_num = $t_table->tableNum();
                                     if (is_numeric($vs_field)) {
                                         $vs_fld_num = 'I' . $vs_field;
                                         $vn_fld_num = (int) $vs_field;
                                     } else {
                                         $vn_fld_num = $this->getFieldNum($vs_table, $vs_field);
                                         $vs_fld_num = 'I' . $vn_fld_num;
                                         if (!strlen($vn_fld_num)) {
                                             $t_element = new ca_metadata_elements();
                                             if ($t_element->load(array('element_code' => $vs_sub_field ? $vs_sub_field : $vs_field))) {
                                                 $vn_fld_num = $t_element->getPrimaryKey();
                                                 $vs_fld_num = 'A' . $vn_fld_num;
                                                 //
                                                 // For certain types of attributes we can directly query the
                                                 // attributes in the database rather than using the full text index
                                                 // This allows us to do "intelligent" querying... for example on date ranges
                                                 // parsed from natural language input and for length dimensions using unit conversion
                                                 //
                                                 switch ($t_element->get('datatype')) {
                                                     case 2:
                                                         // dates
                                                         $vb_exact = $vs_term[0] == "#" ? true : false;
                                                         // dates prepended by "#" are considered "exact" or "contained - the matched dates must be wholly contained by the search term
                                                         if ($vb_exact) {
                                                             $vs_raw_term = substr($vs_term, 1);
                                                             if ($this->opo_tep->parse($vs_term)) {
                                                                 $va_dates = $this->opo_tep->getHistoricTimestamps();
                                                                 // TODO: fix date handling to reflect distinctions in ranges
                                                                 $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term('[' . $this->opo_tep->getText(array('start_as_iso8601' => true)) . " TO " . $this->opo_tep->getText(array('end_as_iso8601' => true)) . ']', $vs_table . '.' . $vs_fld_num));
                                                             }
                                                         } else {
                                                             if ($this->opo_tep->parse($vs_term)) {
                                                                 $va_dates = $this->opo_tep->getHistoricTimestamps();
                                                                 // TODO: fix date handling to reflect distinctions in ranges
                                                                 $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term('[' . $this->opo_tep->getText(array('start_as_iso8601' => true)) . " TO " . $this->opo_tep->getText(array('end_as_iso8601' => true)) . ']', $vs_table . '.' . $vs_fld_num));
                                                             }
                                                         }
                                                         break;
                                                     case 4:
                                                         // geocode
                                                         $t_geocode = new GeocodeAttributeValue();
                                                         if ($va_coords = caParseGISSearch($vs_term)) {
                                                             $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term('[' . $va_coords['min_latitude'] . ',' . $va_coords['min_longitude'] . " TO " . $va_coords['max_latitude'] . ',' . $va_coords['max_longitude'] . ']', $vs_table . '.' . $vs_fld_num));
                                                         }
                                                         break;
                                                     case 6:
                                                         // currency
                                                         $t_cur = new CurrencyAttributeValue();
                                                         $va_parsed_value = $t_cur->parseValue($vs_term, $t_element->getFieldValuesArray());
                                                         $vn_amount = (double) $va_parsed_value['value_decimal1'];
                                                         $vs_currency = preg_replace('![^A-Z0-9]+!', '', $va_parsed_value['value_longtext1']);
                                                         $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term($vn_amount, $vs_table . '.' . $vs_fld_num));
                                                         break;
                                                     case 8:
                                                         // length
                                                         $t_len = new LengthAttributeValue();
                                                         $va_parsed_value = $t_len->parseValue($vs_term, $t_element->getFieldValuesArray());
                                                         $vn_len = (double) $va_parsed_value['value_decimal1'];
                                                         // this is always in meters so we can compare this value to the one in the database
                                                         $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term($vn_len, $vs_table . '.' . $vs_fld_num));
                                                         break;
                                                     case 9:
                                                         // weight
                                                         $t_weight = new WeightAttributeValue();
                                                         $va_parsed_value = $t_weight->parseValue($vs_term, $t_element->getFieldValuesArray());
                                                         $vn_weight = (double) $va_parsed_value['value_decimal1'];
                                                         // this is always in kilograms so we can compare this value to the one in the database
                                                         $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term($vn_weight, $vs_table . '.' . $vs_fld_num));
                                                         break;
                                                     case 10:
                                                         // timecode
                                                         $t_timecode = new TimecodeAttributeValue();
                                                         $va_parsed_value = $t_timecode->parseValue($vs_term, $t_element->getFieldValuesArray());
                                                         $vn_timecode = (double) $va_parsed_value['value_decimal1'];
                                                         $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term($vn_timecode, $vs_table . '.' . $vs_fld_num));
                                                         break;
                                                     case 11:
                                                         // integer
                                                         $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term((double) $vs_term, $vs_table . '.' . $vs_fld_num));
                                                         break;
                                                     case 12:
                                                         // decimal
                                                         $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term((double) $vs_term, $vs_table . '.' . $vs_fld_num));
                                                         break;
                                                     default:
                                                         // everything else
                                                         $o_lucene_query_element->getTerm()->field = $vs_table . '.' . $vs_fld_num;
                                                         break;
                                                 }
                                             } else {
                                                 $vn_fld_num = false;
                                                 $vs_fld_num = $vs_field;
                                             }
                                         }
                                     }
                                 }
                             }
                         }
                     }
                     break;
             }
             $va_terms[] = $o_lucene_query_element;
             $va_signs[] = is_array($va_old_signs) ? array_key_exists($vn_i, $va_old_signs) ? $va_old_signs[$vn_i] : true : true;
             $vn_i++;
         }
         $o_rewritten_query = new Zend_Search_Lucene_Search_Query_Boolean($va_terms, $va_signs);
         $ps_search_expression = $this->_queryToString($o_rewritten_query);
     }
     if (is_array($pa_filters) && sizeof($pa_filters) && ($vs_filter_query = $this->_filterValueToQueryValue($pa_filters))) {
         $ps_search_expression = "({$ps_search_expression}) AND ({$vs_filter_query})";
     }
     if (preg_match_all("!([A-Za-z0-9_\\-\\.]+)[/]{1}([A-Za-z0-9_\\-]+):(\"[^\"]*\")!", $ps_search_expression, $va_matches) || preg_match_all("!([A-Za-z0-9_\\-\\.]+)[/]{1}([A-Za-z0-9_\\-]+):([^ ]*)!", $ps_search_expression, $va_matches)) {
         foreach ($va_matches[0] as $vn_i => $vs_element) {
             $vs_fld = $va_matches[1][$vn_i];
             if (!($vs_rel_type = trim($va_matches[2][$vn_i]))) {
                 continue;
             }
             $va_tmp = explode(".", $vs_fld);
             $vs_rel_table = caGetRelationshipTableName($pn_subject_tablenum, $va_tmp[0]);
             $va_rel_type_ids = $vs_rel_type && $vs_rel_table ? caMakeRelationshipTypeIDList($vs_rel_table, array($vs_rel_type)) : null;
             $va_new_elements = array();
             foreach ($va_rel_type_ids as $vn_rel_type_id) {
                 $va_new_elements[] = "(" . $va_matches[1][$vn_i] . "/" . $vn_rel_type_id . ":" . $va_matches[3][$vn_i] . ")";
             }
             $ps_search_expression = str_replace($vs_element, "(" . join(" OR ", $va_new_elements) . ")", $ps_search_expression);
         }
     }
     $ps_search_expression = str_replace("/", '\\/', $ps_search_expression);
     // escape forward slashes used to delimit relationship type qualifier
     Debug::msg("[SOLR] Running query {$ps_search_expression}");
     try {
         $vo_http_client = new Zend_Http_Client();
         $vo_http_client->setUri($this->ops_search_solr_url . "/" . $this->opo_datamodel->getTableName($pn_subject_tablenum) . "/select");
         $vo_http_client->setParameterGet($va_get = array('q' => utf8_decode($ps_search_expression), 'wt' => 'json', 'fl' => $this->opo_datamodel->getTablePrimaryKeyName($pn_subject_tablenum), 'start' => $this->getOption('start'), 'rows' => $this->getOption('limit')));
         $vo_http_response = $vo_http_client->request();
         $va_result = json_decode($vo_http_response->getBody(), true);
     } catch (Exception $e) {
         caLogEvent('ERR', _t('Could not connect to SOLR server: %1', $e->getMessage()), 'Solr->search()');
         $va_result["response"]["docs"] = array();
     }
     return new WLPlugSearchEngineSolrResult($va_result["response"]["docs"], $pn_subject_tablenum);
 }
コード例 #6
0
ファイル: BrowseEngine.php プロジェクト: kai-iak/pawtucket2
 /**
  * Perform the browse using currently applied criteria, calculating the result set and browse facets 
  * required for subsequent browse refinement. You need to call execute() after setting up your browse
  * criteria and options to:
  *		• Get the result set reflecting the current browse state
  *		• Fetch browse facets that reflect the current browse state
  *
  * @param array $pa_options Options include:
  *		checkAccess = array of access values to filter facets that have an 'access' field by
  *		noCache = don't use cached browse results
  *		showDeleted = if set to true, related items that have been deleted are returned. Default is false.
  *		limitToModifiedOn = if set returned results will be limited to rows modified within the specified date range. The value should be a date/time expression parse-able by TimeExpressionParser
  *		user_id = If set item level access control is performed relative to specified user_id, otherwise defaults to logged in user
  *
  * @return bool True on success, null if the browse could not be executed (Eg. no settings), false no error
  */
 public function execute($pa_options = null)
 {
     global $AUTH_CURRENT_USER_ID;
     if (!is_array($this->opa_browse_settings)) {
         return null;
     }
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     $vn_user_id = caGetOption('user_id', $pa_options, $AUTH_CURRENT_USER_ID, array('castTo' => 'int'));
     $vb_no_cache = caGetOption('noCache', $pa_options, caGetOption('no_cache', $pa_options, false, array('castTo' => 'bool')), array('castTo' => 'bool'));
     $va_params = $this->opo_ca_browse_cache->getParameters();
     $vb_need_to_cache_facets = false;
     $vb_results_cached = false;
     $vb_need_to_save_in_cache = false;
     $vs_cache_key = $this->opo_ca_browse_cache->getCurrentCacheKey();
     if ($this->opo_ca_browse_cache->load($vs_cache_key)) {
         $vn_created_on = $this->opo_ca_browse_cache->getParameter('created_on');
         //$t_new_browse->get('created_on', array('getDirectDate' => true));
         $va_criteria = $this->getCriteria();
         if (!$vb_no_cache && intval(time() - $vn_created_on) < $this->opo_ca_browse_config->get('cache_timeout')) {
             $vb_results_cached = true;
             $this->opo_ca_browse_cache->setParameter('created_on', time() + $this->opo_ca_browse_config->get('cache_timeout'));
             $vb_need_to_save_in_cache = true;
             Debug::msg("Cache hit for {$vs_cache_key}");
         } else {
             $va_criteria = $this->getCriteria();
             //$this->opo_ca_browse_cache->remove();
             //$this->opo_ca_browse_cache->setParameter('criteria', $va_criteria);
             $vb_need_to_save_in_cache = true;
             $vb_need_to_cache_facets = true;
             Debug::msg("Cache expire for {$vs_cache_key}");
         }
     } else {
         $va_criteria = $this->getCriteria();
         $vb_need_to_save_in_cache = true;
         Debug::msg("Cache miss for {$vs_cache_key}");
     }
     if (!$vb_results_cached) {
         $this->opo_ca_browse_cache->setParameter('sort', null);
         $this->opo_ca_browse_cache->setParameter('created_on', time());
         $this->opo_ca_browse_cache->setParameter('table_num', $this->opn_browse_table_num);
         $vb_need_to_cache_facets = true;
     }
     $this->opb_criteria_have_changed = false;
     $t_item = $this->opo_datamodel->getInstanceByTableName($this->ops_browse_table_name, true);
     $va_results = array();
     if (is_array($va_criteria) && sizeof($va_criteria) > 0) {
         if (!$vb_results_cached) {
             $va_acc = array();
             $vn_i = 0;
             foreach ($va_criteria as $vs_facet_name => $va_row_ids) {
                 $vs_target_browse_table_name = $t_item->tableName();
                 $vs_target_browse_table_num = $t_item->tableNum();
                 $vs_target_browse_table_pk = $t_item->primaryKey();
                 $va_facet_info = $this->getInfoForFacet($vs_facet_name);
                 $va_row_ids = array_keys($va_row_ids);
                 $vs_relative_to_join = '';
                 switch ($va_facet_info['type']) {
                     # -----------------------------------------------------
                     case 'has':
                         $vs_rel_table_name = $va_facet_info['table'];
                         $va_joins = array();
                         if ($va_facet_info['relative_to']) {
                             if ($va_relative_execute_sql_data = $this->_getRelativeExecuteSQLData($va_facet_info['relative_to'], $pa_options)) {
                                 $va_joins = array_merge($va_joins, $va_relative_execute_sql_data['relative_joins']);
                                 $vs_target_browse_table_name = $va_relative_execute_sql_data['target_table_name'];
                                 $vs_target_browse_table_num = $va_relative_execute_sql_data['target_table_num'];
                                 $vs_target_browse_table_pk = $va_relative_execute_sql_data['target_table_pk'];
                             }
                         }
                         if ($va_facet_info['element_code']) {
                             $t_element = new ca_metadata_elements();
                             if (!$t_element->load(array('element_code' => $va_facet_info['element_code']))) {
                                 break;
                             }
                             $vs_element_code = $va_facet_info['element_code'];
                             $vn_state = array_pop($va_row_ids);
                             if ($vn_state == 0) {
                                 $va_wheres[] = $this->ops_browse_table_name . '.' . $t_item->primaryKey() . " NOT IN (SELECT row_id FROM ca_attributes WHERE table_num = " . $t_item->tableNum() . " AND element_id = " . $t_element->getPrimaryKey() . ")";
                             } else {
                                 $va_joins[] = "INNER JOIN ca_attributes AS caa ON caa.row_id = " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . " AND caa.table_num = " . $t_item->tableNum();
                                 $va_wheres[] = "caa.element_id = " . $t_element->getPrimaryKey();
                             }
                         } else {
                             if (!is_array($va_restrict_to_relationship_types = $va_facet_info['restrict_to_relationship_types'])) {
                                 $va_restrict_to_relationship_types = array();
                             }
                             $va_restrict_to_relationship_types = $this->_getRelationshipTypeIDs($va_restrict_to_relationship_types, $va_facet_info['relationship_table']);
                             if (!is_array($va_exclude_relationship_types = $va_facet_info['exclude_relationship_types'])) {
                                 $va_exclude_relationship_types = array();
                             }
                             $va_exclude_relationship_types = $this->_getRelationshipTypeIDs($va_exclude_relationship_types, $va_facet_info['relationship_table']);
                             $vn_table_num = $this->opo_datamodel->getTableNum($vs_rel_table_name);
                             $vs_rel_table_pk = $this->opo_datamodel->getTablePrimaryKeyName($vn_table_num);
                             switch (sizeof($va_path = array_keys($this->opo_datamodel->getPath($vs_target_browse_table_name, $vs_rel_table_name)))) {
                                 case 3:
                                     $t_item_rel = $this->opo_datamodel->getInstanceByTableName($va_path[1], true);
                                     $t_rel_item = $this->opo_datamodel->getInstanceByTableName($va_path[2], true);
                                     $vs_key = 'relation_id';
                                     break;
                                 case 2:
                                     $t_item_rel = null;
                                     $t_rel_item = $this->opo_datamodel->getInstanceByTableName($va_path[1], true);
                                     $vs_key = $t_rel_item->primaryKey();
                                     break;
                                 default:
                                     // bad related table
                                     return null;
                                     break;
                             }
                             $vs_cur_table = array_shift($va_path);
                             $vn_state = array_pop($va_row_ids);
                             foreach ($va_path as $vs_join_table) {
                                 $va_rel_info = $this->opo_datamodel->getRelationships($vs_cur_table, $vs_join_table);
                                 $va_joins[] = ($vn_state ? 'INNER' : 'LEFT') . ' JOIN ' . $vs_join_table . ' ON ' . $vs_cur_table . '.' . $va_rel_info[$vs_cur_table][$vs_join_table][0][0] . ' = ' . $vs_join_table . '.' . $va_rel_info[$vs_cur_table][$vs_join_table][0][1] . "\n";
                                 $vs_cur_table = $vs_join_table;
                             }
                             $va_wheres = array();
                             if (sizeof($va_restrict_to_relationship_types) > 0 && is_object($t_item_rel) && (bool) $vn_state) {
                                 $va_wheres[] = "(" . $t_item_rel->tableName() . ".type_id IN (" . join(',', $va_restrict_to_relationship_types) . "))";
                             }
                             if (sizeof($va_exclude_relationship_types) > 0 && is_object($t_item_rel) && (bool) $vn_state) {
                                 $va_wheres[] = "(" . $t_item_rel->tableName() . ".type_id NOT IN (" . join(',', $va_exclude_relationship_types) . "))";
                             }
                             if (!(bool) $vn_state) {
                                 // no option
                                 $va_wheres[] = "(" . $t_rel_item->tableName() . "." . $t_rel_item->primaryKey() . " IS NULL)";
                                 if ($t_rel_item->hasField('deleted')) {
                                     $va_wheres[] = "((" . $t_rel_item->tableName() . ".deleted = 0) OR (" . $t_rel_item->tableName() . ".deleted IS NULL))";
                                 }
                                 if (isset($pa_options['checkAccess']) && is_array($pa_options['checkAccess']) && sizeof($pa_options['checkAccess']) && $t_rel_item->hasField('access')) {
                                     $va_wheres[] = "((" . $t_rel_item->tableName() . ".access NOT IN (" . join(',', $pa_options['checkAccess']) . ")) OR ((" . $t_rel_item->tableName() . "." . $t_rel_item->primaryKey() . " IS NULL) AND (" . $t_rel_item->tableName() . ".access IS NULL)))";
                                 }
                             } else {
                                 // yes option
                                 $va_wheres[] = "(" . $t_rel_item->tableName() . "." . $t_rel_item->primaryKey() . " IS NOT NULL)";
                                 if ($t_rel_item->hasField('deleted')) {
                                     $va_wheres[] = "(" . $t_rel_item->tableName() . ".deleted = 0)";
                                 }
                                 if (isset($pa_options['checkAccess']) && is_array($pa_options['checkAccess']) && sizeof($pa_options['checkAccess']) && $t_rel_item->hasField('access')) {
                                     $va_wheres[] = "(" . $t_rel_item->tableName() . ".access IN (" . join(',', $pa_options['checkAccess']) . "))";
                                 }
                             }
                         }
                         if ($t_item->hasField('deleted')) {
                             $va_wheres[] = "(" . $t_item->tableName() . ".deleted = 0)";
                         }
                         if (isset($pa_options['checkAccess']) && is_array($pa_options['checkAccess']) && sizeof($pa_options['checkAccess']) && $t_item->hasField('access')) {
                             $va_wheres[] = "(" . $t_item->tableName() . ".access IN (" . join(',', $pa_options['checkAccess']) . "))";
                         }
                         $vs_join_sql = join("\n", $va_joins);
                         $vs_where_sql = '';
                         if (sizeof($va_wheres) > 0) {
                             $vs_where_sql = ' WHERE ' . join(' AND ', $va_wheres);
                         }
                         if ($vn_i == 0) {
                             $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_join_sql}\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_where_sql}\n\t\t\t\t\t\t\t\t\t\t\t";
                             $qr_res = $this->opo_db->query($vs_sql);
                         } else {
                             $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_join_sql}\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_where_sql}";
                             $qr_res = $this->opo_db->query($vs_sql);
                         }
                         $va_acc[$vn_i] = $qr_res->getAllFieldValues($this->ops_browse_table_name . '.' . $t_item->primaryKey());
                         $vn_i++;
                         break;
                         # -----------------------------------------------------
                     # -----------------------------------------------------
                     case 'label':
                         if (!($t_label = $t_item->getLabelTableInstance())) {
                             break;
                         }
                         $vs_label_item_pk = $vs_item_pk = $t_item->primaryKey();
                         $vs_label_table_name = $t_label->tableName();
                         $vs_label_pk = $t_label->primaryKey();
                         $vs_label_display_field = $t_item->getLabelDisplayField();
                         if ($va_facet_info['relative_to']) {
                             if ($va_relative_execute_sql_data = $this->_getRelativeExecuteSQLData($va_facet_info['relative_to'], $pa_options)) {
                                 $vs_target_browse_table_name = $va_relative_execute_sql_data['target_table_name'];
                                 $vs_target_browse_table_num = $va_relative_execute_sql_data['target_table_num'];
                                 $vs_target_browse_table_pk = $va_relative_execute_sql_data['target_table_pk'];
                                 $t_target = $this->opo_datamodel->getInstanceByTableName($va_facet_info['relative_to'], true);
                                 $t_target_label = $t_target->getLabelTableInstance();
                                 $vs_item_pk = $t_target->primaryKey();
                                 $vs_label_table_name = $t_target_label->tableName();
                                 $vs_label_item_pk = $t_target_label->primaryKey();
                                 $va_relative_to_join = $va_relative_execute_sql_data['relative_joins'];
                                 $va_relative_to_join[] = "INNER JOIN {$vs_label_table_name} ON {$vs_label_table_name}.{$vs_label_item_pk} = {$vs_target_browse_table_name}.{$vs_target_browse_table_pk}";
                             }
                         } else {
                             $va_relative_to_join = array("INNER JOIN {$vs_label_table_name} ON {$vs_label_table_name}.{$vs_label_item_pk} = {$vs_target_browse_table_name}.{$vs_target_browse_table_pk}");
                         }
                         $vs_relative_to_join = join("\n", $va_relative_to_join);
                         $va_labels = $t_item->getPreferredDisplayLabelsForIDs($va_row_ids);
                         foreach ($va_row_ids as $vn_row_id) {
                             if ($vn_i == 0) {
                                 $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . "." . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t\t{$vs_label_table_name}.{$vs_label_display_field} = ?";
                                 //print "$vs_sql [".intval($this->opn_browse_table_num)."]<hr>";
                                 $qr_res = $this->opo_db->query($vs_sql, $va_labels[$vn_row_id]);
                             } else {
                                 $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . "." . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t\t{$vs_label_table_name}.{$vs_label_display_field} = ?";
                                 $qr_res = $this->opo_db->query($vs_sql, $va_labels[$vn_row_id]);
                             }
                             $va_acc[$vn_i] = $qr_res->getAllFieldValues($this->ops_browse_table_name . '.' . $t_item->primaryKey());
                             $vn_i++;
                         }
                         break;
                         # -----------------------------------------------------
                     # -----------------------------------------------------
                     case 'field':
                         $vs_field_name = $va_facet_info['field'];
                         $vs_table_name = $this->ops_browse_table_name;
                         if ($va_facet_info['relative_to']) {
                             if ($va_relative_execute_sql_data = $this->_getRelativeExecuteSQLData($va_facet_info['relative_to'], $pa_options)) {
                                 $va_relative_to_join = $va_relative_execute_sql_data['relative_joins'];
                                 $vs_relative_to_join = join("\n", $va_relative_to_join);
                                 $vs_table_name = $vs_target_browse_table_name = $va_relative_execute_sql_data['target_table_name'];
                                 $vs_target_browse_table_num = $va_relative_execute_sql_data['target_table_num'];
                                 $vs_target_browse_table_pk = $va_relative_execute_sql_data['target_table_pk'];
                             }
                         }
                         foreach ($va_row_ids as $vn_row_id) {
                             $vn_row_id = urldecode(str_replace('&#47;', '/', $vn_row_id));
                             if ($vn_i == 0) {
                                 $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t\t({$vs_table_name}.{$vs_field_name} = ?)";
                                 $qr_res = $this->opo_db->query($vs_sql, (string) $vn_row_id);
                             } else {
                                 $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t\t({$vs_table_name}.{$vs_field_name} = ?)";
                                 $qr_res = $this->opo_db->query($vs_sql, (string) $vn_row_id);
                             }
                             $va_acc[$vn_i] = $qr_res->getAllFieldValues($this->ops_browse_table_name . '.' . $t_item->primaryKey());
                             $vn_i++;
                         }
                         break;
                         # -----------------------------------------------------
                     # -----------------------------------------------------
                     case 'attribute':
                         $t_element = new ca_metadata_elements();
                         if (!$t_element->load(array('element_code' => $va_facet_info['element_code']))) {
                             return array();
                         }
                         $vn_datatype = $t_element->get('datatype');
                         if ($va_facet_info['relative_to']) {
                             if ($va_relative_execute_sql_data = $this->_getRelativeExecuteSQLData($va_facet_info['relative_to'], $pa_options)) {
                                 $va_relative_to_join = $va_relative_execute_sql_data['relative_joins'];
                                 $vs_relative_to_join = join("\n", $va_relative_to_join);
                                 $vs_target_browse_table_name = $va_relative_execute_sql_data['target_table_name'];
                                 $vs_target_browse_table_num = $va_relative_execute_sql_data['target_table_num'];
                                 $vs_target_browse_table_pk = $va_relative_execute_sql_data['target_table_pk'];
                             }
                         }
                         // TODO: check that it is a *single-value* (ie. no hierarchical ca_metadata_elements) Text or Number attribute
                         // (do we support other types as well?)
                         $vn_element_id = $t_element->getPrimaryKey();
                         $o_attr = Attribute::getValueInstance($vn_datatype);
                         foreach ($va_row_ids as $vn_row_id) {
                             $vn_row_id = urldecode($vn_row_id);
                             $vn_row_id = str_replace('&#47;', '/', $vn_row_id);
                             $va_value = $o_attr->parseValue($vn_row_id, $t_element->getFieldValuesArray());
                             $va_attr_sql = array();
                             $va_attr_values = array(intval($vs_target_browse_table_num), $vn_element_id);
                             if (is_array($va_value)) {
                                 foreach ($va_value as $vs_f => $vs_v) {
                                     if ($vn_datatype == __CA_ATTRIBUTE_VALUE_LIST__) {
                                         if ($vs_f != 'item_id') {
                                             continue;
                                         }
                                         // Include sub-items
                                         $t_list_item = new ca_list_items();
                                         $va_item_ids = $t_list_item->getHierarchy((int) $vs_v, array('idsOnly' => true, 'includeSelf' => true));
                                         $va_item_ids[] = (int) $vs_v;
                                         $va_attr_sql[] = "(ca_attribute_values.{$vs_f} IN (?))";
                                         $va_attr_values[] = $va_item_ids;
                                     } else {
                                         $va_attr_sql[] = "(ca_attribute_values.{$vs_f} " . (is_null($vs_v) ? " IS " : " = ") . " ?)";
                                         $va_attr_values[] = $vs_v;
                                     }
                                 }
                             }
                             if ($vs_attr_sql = join(" AND ", $va_attr_sql)) {
                                 $vs_attr_sql = " AND " . $vs_attr_sql;
                             }
                             if ($vn_i == 0) {
                                 $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\t\tINNER JOIN ca_attributes ON ca_attributes.row_id = {$vs_target_browse_table_name}.{$vs_target_browse_table_pk} AND ca_attributes.table_num = ?\n\t\t\t\t\t\t\t\t\t\t\t\tINNER JOIN ca_attribute_values ON ca_attribute_values.attribute_id = ca_attributes.attribute_id\n\t\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t\t(ca_attribute_values.element_id = ?) {$vs_attr_sql}";
                                 $qr_res = $this->opo_db->query($vs_sql, $va_attr_values);
                             } else {
                                 $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\t\tINNER JOIN ca_attributes ON ca_attributes.row_id = {$vs_target_browse_table_name}.{$vs_target_browse_table_pk} AND ca_attributes.table_num = ?\n\t\t\t\t\t\t\t\t\t\t\t\tINNER JOIN ca_attribute_values ON ca_attribute_values.attribute_id = ca_attributes.attribute_id\n\t\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t\t(ca_attribute_values.element_id = ?) {$vs_attr_sql}";
                                 $qr_res = $this->opo_db->query($vs_sql, $va_attr_values);
                             }
                             $va_acc[$vn_i] = $qr_res->getAllFieldValues($this->ops_browse_table_name . '.' . $t_item->primaryKey());
                             $vn_i++;
                         }
                         break;
                         # -----------------------------------------------------
                     # -----------------------------------------------------
                     case 'normalizedDates':
                         $t_element = new ca_metadata_elements();
                         $vb_is_element = $vb_is_field = false;
                         if (!($vb_is_element = $t_element->load(array('element_code' => $va_facet_info['element_code']))) && !($vb_is_field = $t_item->hasField($va_facet_info['element_code']) && $t_item->getFieldInfo($va_facet_info['element_code'], 'FIELD_TYPE') === FT_HISTORIC_DATERANGE)) {
                             return array();
                         }
                         // TODO: check that it is a *single-value* (ie. no hierarchical ca_metadata_elements) DateRange attribute
                         $vs_normalization = $va_facet_info['normalization'];
                         $o_tep = new TimeExpressionParser();
                         if ($va_facet_info['relative_to']) {
                             if ($va_relative_execute_sql_data = $this->_getRelativeExecuteSQLData($va_facet_info['relative_to'], $pa_options)) {
                                 $va_relative_to_join = $va_relative_execute_sql_data['relative_joins'];
                                 $vs_relative_to_join = join("\n", $va_relative_to_join);
                                 $vs_target_browse_table_name = $va_relative_execute_sql_data['target_table_name'];
                                 $vs_target_browse_table_num = $va_relative_execute_sql_data['target_table_num'];
                                 $vs_target_browse_table_pk = $va_relative_execute_sql_data['target_table_pk'];
                             }
                         }
                         $vn_element_id = $vb_is_element ? $t_element->getPrimaryKey() : null;
                         $vs_browse_start_fld = $vs_browse_start_fld = null;
                         if ($vb_is_field) {
                             $vs_browse_start_fld = $t_item->getFieldInfo($va_facet_info['element_code'], 'START');
                             $vs_browse_end_fld = $t_item->getFieldInfo($va_facet_info['element_code'], 'END');
                         }
                         foreach ($va_row_ids as $vn_row_id) {
                             $vn_row_id = urldecode($vn_row_id);
                             $va_dates = null;
                             if ($vn_row_id !== 'null') {
                                 if (!$o_tep->parse($vn_row_id)) {
                                     continue;
                                 }
                                 // invalid date?
                                 $va_dates = $o_tep->getHistoricTimestamps();
                             }
                             if ($vb_is_element) {
                                 if (is_null($va_dates)) {
                                     $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\t\t\tINNER JOIN ca_attributes ON ca_attributes.row_id = " . $vs_target_browse_table_name . '.' . $vs_target_browse_table_pk . " AND ca_attributes.table_num = ?\n\t\t\t\t\t\t\t\t\t\t\t\t\tINNER JOIN ca_attribute_values ON ca_attribute_values.attribute_id = ca_attributes.attribute_id\n\t\t\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(ca_attribute_values.element_id = ?) \n\t\t\t\t\t\t\t\t\t\t\t\t\t\tAND\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(ca_attribute_values.value_decimal1 IS NULL)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tAND \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(ca_attribute_values.value_decimal2 IS NULL)\n\t\t\t\t\t\t\t\t\t\t\t\t";
                                     $qr_res = $this->opo_db->query($vs_sql, intval($vs_target_browse_table_num), $vn_element_id);
                                 } else {
                                     $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\t\t\tINNER JOIN ca_attributes ON ca_attributes.row_id = " . $vs_target_browse_table_name . '.' . $vs_target_browse_table_pk . " AND ca_attributes.table_num = ?\n\t\t\t\t\t\t\t\t\t\t\t\t\tINNER JOIN ca_attribute_values ON ca_attribute_values.attribute_id = ca_attributes.attribute_id\n\t\t\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(ca_attribute_values.element_id = ?) AND\n\t\t\t\t\t\t\t\t\t\t\t\t\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(ca_attribute_values.value_decimal1 <= ?) AND\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(ca_attribute_values.value_decimal2 >= ?)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tOR\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(ca_attribute_values.value_decimal1 BETWEEN ? AND ?)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tOR \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(ca_attribute_values.value_decimal2 BETWEEN ? AND ?)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t";
                                     $qr_res = $this->opo_db->query($vs_sql, intval($vs_target_browse_table_num), $vn_element_id, $va_dates['start'], $va_dates['end'], $va_dates['start'], $va_dates['end'], $va_dates['start'], $va_dates['end']);
                                 }
                             } else {
                                 // is intrinsic
                                 if (is_null($va_dates)) {
                                     $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t({$this->ops_browse_table_name}.{$vs_browse_start_fld} IS NULL)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\tAND \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t({$this->ops_browse_table_name}.{$vs_browse_end_fld} IS NULL)\n\t\t\t\t\t\t\t\t\t\t\t\t";
                                     $qr_res = $this->opo_db->query($vs_sql);
                                 } else {
                                     $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t(\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t({$this->ops_browse_table_name}.{$vs_browse_start_fld} <= ?) AND\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t({$this->ops_browse_table_name}.{$vs_browse_end_fld} >= ?)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tOR\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t({$this->ops_browse_table_name}.{$vs_browse_start_fld} BETWEEN ? AND ?)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\tOR \n\t\t\t\t\t\t\t\t\t\t\t\t\t\t\t({$this->ops_browse_table_name}.{$vs_browse_end_fld} BETWEEN ? AND ?)\n\t\t\t\t\t\t\t\t\t\t\t\t\t\t)\n\t\t\t\t\t\t\t\t\t\t\t\t";
                                     $qr_res = $this->opo_db->query($vs_sql, $va_dates['start'], $va_dates['end'], $va_dates['start'], $va_dates['end'], $va_dates['start'], $va_dates['end']);
                                 }
                             }
                             $va_acc[$vn_i] = $qr_res->getAllFieldValues($this->ops_browse_table_name . '.' . $t_item->primaryKey());
                             $vn_i++;
                         }
                         break;
                         # -----------------------------------------------------
                     # -----------------------------------------------------
                     case 'normalizedLength':
                         $t_element = new ca_metadata_elements();
                         $vb_is_element = $vb_is_field = false;
                         if (!($vb_is_element = $t_element->load(array('element_code' => $va_facet_info['element_code']))) && !($vb_is_field = $t_item->hasField($va_facet_info['element_code']) && $t_item->getFieldInfo($va_facet_info['element_code'], 'FIELD_TYPE') === FT_HISTORIC_DATERANGE)) {
                             return array();
                         }
                         // TODO: check that it is a *single-value* (ie. no hierarchical ca_metadata_elements) DateRange attribute
                         $vs_normalization = $va_facet_info['normalization'];
                         $o_tep = new TimeExpressionParser();
                         if ($va_facet_info['relative_to']) {
                             if ($va_relative_execute_sql_data = $this->_getRelativeExecuteSQLData($va_facet_info['relative_to'], $pa_options)) {
                                 $va_relative_to_join = $va_relative_execute_sql_data['relative_joins'];
                                 $vs_relative_to_join = join("\n", $va_relative_to_join);
                                 $vs_target_browse_table_name = $va_relative_execute_sql_data['target_table_name'];
                                 $vs_target_browse_table_num = $va_relative_execute_sql_data['target_table_num'];
                                 $vs_target_browse_table_pk = $va_relative_execute_sql_data['target_table_pk'];
                             }
                         }
                         $vn_element_id = $vb_is_element ? $t_element->getPrimaryKey() : null;
                         $vs_browse_start_fld = $vs_browse_start_fld = null;
                         if ($vb_is_field) {
                             $vs_browse_start_fld = $t_item->getFieldInfo($va_facet_info['element_code'], 'START');
                             $vs_browse_end_fld = $t_item->getFieldInfo($va_facet_info['element_code'], 'END');
                         }
                         if (!($vs_output_units = caGetLengthUnitType($vs_units = caGetOption('units', $va_facet_info, 'm')))) {
                             $vs_output_units = Zend_Measure_Length::METER;
                         }
                         $vs_increment = caGetOption('increment', $va_facet_info, '1 m');
                         $vo_increment = caParseLengthDimension($vs_increment);
                         $vn_increment_in_current_units = (double) $vo_increment->convertTo($vs_output_units, 6, 'en_US');
                         foreach ($va_row_ids as $vn_row_id) {
                             $vn_start = urldecode($vn_row_id);
                             // is start dimension
                             // calculate end dimension
                             $vn_end = $vn_start + $vn_increment_in_current_units;
                             // convert to meters
                             $vo_start = new Zend_Measure_Length($vn_start, $vs_output_units, 'en_US');
                             $vo_end = new Zend_Measure_Length($vn_end, $vs_output_units, 'en_US');
                             $vn_start_in_meters = (double) $vo_start->convertTo(Zend_Measure_Length::METER, 6, 'en_US');
                             $vn_end_in_meters = (double) $vo_end->convertTo(Zend_Measure_Length::METER, 6, 'en_US');
                             $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\tINNER JOIN ca_attributes ON ca_attributes.row_id = " . $vs_target_browse_table_name . '.' . $vs_target_browse_table_pk . " AND ca_attributes.table_num = ?\n\t\t\t\t\t\t\t\t\t\t\tINNER JOIN ca_attribute_values ON ca_attribute_values.attribute_id = ca_attributes.attribute_id\n\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t(ca_attribute_values.element_id = ?) AND\n\t\t\t\t\t\t\t\t\t\t\t\t(ca_attribute_values.value_decimal1 BETWEEN ? AND ?)\n\t\t\t\t\t\t\t\t\t\t";
                             $qr_res = $this->opo_db->query($vs_sql, intval($vs_target_browse_table_num), $vn_element_id, $vn_start_in_meters, $vn_end_in_meters);
                             $va_acc[$vn_i] = $qr_res->getAllFieldValues($this->ops_browse_table_name . '.' . $t_item->primaryKey());
                             $vn_i++;
                         }
                         break;
                         # -----------------------------------------------------
                     # -----------------------------------------------------
                     case 'authority':
                         $vs_rel_table_name = $va_facet_info['table'];
                         if (!is_array($va_restrict_to_relationship_types = $va_facet_info['restrict_to_relationship_types'])) {
                             $va_restrict_to_relationship_types = array();
                         }
                         $va_restrict_to_relationship_types = $this->_getRelationshipTypeIDs($va_restrict_to_relationship_types, $va_facet_info['relationship_table']);
                         if (!is_array($va_exclude_relationship_types = $va_facet_info['exclude_relationship_types'])) {
                             $va_exclude_relationship_types = array();
                         }
                         $va_exclude_relationship_types = $this->_getRelationshipTypeIDs($va_exclude_relationship_types, $va_facet_info['relationship_table']);
                         $vn_table_num = $this->opo_datamodel->getTableNum($vs_rel_table_name);
                         $vs_rel_table_pk = $this->opo_datamodel->getTablePrimaryKeyName($vn_table_num);
                         if ($va_facet_info['relative_to']) {
                             if ($va_relative_execute_sql_data = $this->_getRelativeExecuteSQLData($va_facet_info['relative_to'], $pa_options)) {
                                 $va_relative_to_join = $va_relative_execute_sql_data['relative_joins'];
                                 $vs_relative_to_join = join("\n", $va_relative_to_join);
                                 $vs_target_browse_table_name = $va_relative_execute_sql_data['target_table_name'];
                                 $vs_target_browse_table_num = $va_relative_execute_sql_data['target_table_num'];
                                 $vs_target_browse_table_pk = $va_relative_execute_sql_data['target_table_pk'];
                             }
                         }
                         foreach ($va_row_ids as $vn_row_id) {
                             switch (sizeof($va_path = array_keys($this->opo_datamodel->getPath($vs_target_browse_table_name, $vs_rel_table_name)))) {
                                 case 3:
                                     $t_item_rel = $this->opo_datamodel->getInstanceByTableName($va_path[1], true);
                                     $t_rel_item = $this->opo_datamodel->getInstanceByTableName($va_path[2], true);
                                     $vs_key = 'relation_id';
                                     break;
                                 case 2:
                                     $t_item_rel = null;
                                     $t_rel_item = $this->opo_datamodel->getInstanceByTableName($va_path[1], true);
                                     $vs_key = $t_rel_item->primaryKey();
                                     break;
                                 default:
                                     // bad related table
                                     return null;
                                     break;
                             }
                             $vs_cur_table = array_shift($va_path);
                             $va_joins = array();
                             foreach ($va_path as $vs_join_table) {
                                 $va_rel_info = $this->opo_datamodel->getRelationships($vs_cur_table, $vs_join_table);
                                 $va_joins[] = 'INNER JOIN ' . $vs_join_table . ' ON ' . $vs_cur_table . '.' . $va_rel_info[$vs_cur_table][$vs_join_table][0][0] . ' = ' . $vs_join_table . '.' . $va_rel_info[$vs_cur_table][$vs_join_table][0][1] . "\n";
                                 $vs_cur_table = $vs_join_table;
                             }
                             $vs_join_sql = join("\n", $va_joins);
                             $va_wheres = array();
                             if (sizeof($va_restrict_to_relationship_types) > 0 && is_object($t_item_rel)) {
                                 $va_wheres[] = "(" . $t_item_rel->tableName() . ".type_id IN (" . join(',', $va_restrict_to_relationship_types) . "))";
                             }
                             if (sizeof($va_exclude_relationship_types) > 0 && is_object($t_item_rel)) {
                                 $va_wheres[] = "(" . $t_item_rel->tableName() . ".type_id NOT IN (" . join(',', $va_exclude_relationship_types) . "))";
                             }
                             $vs_where_sql = '';
                             if (sizeof($va_wheres) > 0) {
                                 $vs_where_sql = ' AND ' . join(' AND ', $va_wheres);
                             }
                             if ((!isset($va_facet_info['dont_expand_hierarchically']) || !$va_facet_info['dont_expand_hierarchically']) && $t_rel_item->isHierarchical() && $t_rel_item->load((int) $vn_row_id)) {
                                 $vs_hier_left_fld = $t_rel_item->getProperty('HIERARCHY_LEFT_INDEX_FLD');
                                 $vs_hier_right_fld = $t_rel_item->getProperty('HIERARCHY_RIGHT_INDEX_FLD');
                                 $vs_get_item_sql = "{$vs_rel_table_name}.{$vs_hier_left_fld} >= " . $t_rel_item->get($vs_hier_left_fld) . " AND {$vs_rel_table_name}.{$vs_hier_right_fld} <= " . $t_rel_item->get($vs_hier_right_fld);
                                 if ($vn_hier_id_fld = $t_rel_item->getProperty('HIERARCHY_ID_FLD')) {
                                     $vs_get_item_sql .= " AND {$vs_rel_table_name}.{$vn_hier_id_fld} = " . (int) $t_rel_item->get($vn_hier_id_fld);
                                 }
                                 $vs_get_item_sql = "({$vs_get_item_sql})";
                             } else {
                                 $vs_get_item_sql = "({$vs_rel_table_name}.{$vs_rel_table_pk} = " . (int) $vn_row_id . ")";
                             }
                             if ($vn_i == 0) {
                                 $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_join_sql}\n\t\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t\t{$vs_get_item_sql}\n\t\t\t\t\t\t\t\t\t\t\t\t\t{$vs_where_sql}";
                                 $qr_res = $this->opo_db->query($vs_sql);
                             } else {
                                 $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_join_sql}\n\t\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t\t{$vs_get_item_sql}\n\t\t\t\t\t\t\t\t\t\t\t\t\t{$vs_where_sql}";
                                 $qr_res = $this->opo_db->query($vs_sql);
                             }
                             $va_acc[$vn_i] = $qr_res->getAllFieldValues($this->ops_browse_table_name . '.' . $t_item->primaryKey());
                             $vn_i++;
                         }
                         break;
                         # -----------------------------------------------------
                     # -----------------------------------------------------
                     case 'location':
                         foreach ($va_row_ids as $vn_row_id) {
                             $vn_row_id = urldecode($vn_row_id);
                             $va_row_tmp = explode(":", $vn_row_id);
                             if ($vn_i == 0) {
                                 $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t\t({$this->ops_browse_table_name}.current_loc_class = ?)" . (sizeof($va_row_tmp) > 1 ? " AND ({$this->ops_browse_table_name}.current_loc_subclass = ?)" : "") . (sizeof($va_row_tmp) > 2 ? " AND ({$this->ops_browse_table_name}.current_loc_id = ?)" : "");
                                 $qr_res = $this->opo_db->query($vs_sql, $va_row_tmp);
                             } else {
                                 $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t\t({$this->ops_browse_table_name}.current_loc_class = ?)" . (sizeof($va_row_tmp) > 1 ? " AND ({$this->ops_browse_table_name}.current_loc_subclass = ?)" : "") . (sizeof($va_row_tmp) > 2 ? " AND ({$this->ops_browse_table_name}.current_loc_id = ?)" : "");
                                 $qr_res = $this->opo_db->query($vs_sql, $va_row_tmp);
                             }
                             $va_acc[$vn_i] = $qr_res->getAllFieldValues($this->ops_browse_table_name . '.' . $t_item->primaryKey());
                             $vn_i++;
                         }
                         break;
                         # -----------------------------------------------------
                     # -----------------------------------------------------
                     case 'fieldList':
                         $vs_field_name = $va_facet_info['field'];
                         $vs_table_name = $this->ops_browse_table_name;
                         if ($va_facet_info['relative_to']) {
                             if ($va_relative_execute_sql_data = $this->_getRelativeExecuteSQLData($va_facet_info['relative_to'], $pa_options)) {
                                 $va_relative_to_join = $va_relative_execute_sql_data['relative_joins'];
                                 $vs_relative_to_join = join("\n", $va_relative_to_join);
                                 $vs_table_name = $vs_target_browse_table_name = $va_relative_execute_sql_data['target_table_name'];
                                 $vs_target_browse_table_num = $va_relative_execute_sql_data['target_table_num'];
                                 $vs_target_browse_table_pk = $va_relative_execute_sql_data['target_table_pk'];
                             }
                         }
                         foreach ($va_row_ids as $vn_row_id) {
                             $vn_row_id = urldecode($vn_row_id);
                             if ($vn_i == 0) {
                                 $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t\t({$vs_table_name}.{$vs_field_name} = ?)";
                                 $qr_res = $this->opo_db->query($vs_sql, $vn_row_id);
                             } else {
                                 $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t\t({$vs_table_name}.{$vs_field_name} = ?)";
                                 $qr_res = $this->opo_db->query($vs_sql, $vn_row_id);
                             }
                             $va_acc[$vn_i] = $qr_res->getAllFieldValues($this->ops_browse_table_name . '.' . $t_item->primaryKey());
                             $vn_i++;
                         }
                         break;
                         # -----------------------------------------------------
                     # -----------------------------------------------------
                     case 'violations':
                         $vs_field_name = $va_facet_info['field'];
                         $vs_table_name = $this->ops_browse_table_name;
                         if ($va_facet_info['relative_to']) {
                             if ($va_relative_execute_sql_data = $this->_getRelativeExecuteSQLData($va_facet_info['relative_to'], $pa_options)) {
                                 $va_relative_to_join = $va_relative_execute_sql_data['relative_joins'];
                                 $vs_relative_to_join = join("\n", $va_relative_to_join);
                                 $vs_table_name = $vs_target_browse_table_name = $va_relative_execute_sql_data['target_table_name'];
                                 $vs_target_browse_table_num = $va_relative_execute_sql_data['target_table_num'];
                                 $vs_target_browse_table_pk = $va_relative_execute_sql_data['target_table_pk'];
                             }
                         }
                         foreach ($va_row_ids as $vn_row_id) {
                             $vn_row_id = urldecode($vn_row_id);
                             if ($vn_i == 0) {
                                 $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\tINNER JOIN ca_metadata_dictionary_rule_violations ON ca_metadata_dictionary_rule_violations.row_id = " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . " AND ca_metadata_dictionary_rule_violations.table_num = " . $t_item->tableNum() . "\n\t\t\t\t\t\t\t\t\t\t\tINNER JOIN ca_metadata_dictionary_rules ON ca_metadata_dictionary_rules.rule_id = ca_metadata_dictionary_rule_violations.rule_id\n\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t(ca_metadata_dictionary_rules.rule_code = ?)";
                                 $qr_res = $this->opo_db->query($vs_sql, $vn_row_id);
                             } else {
                                 $vs_sql = "\n\t\t\t\t\t\t\t\t\t\t\tSELECT " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . "\n\t\t\t\t\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t\t\t\t\tINNER JOIN ca_metadata_dictionary_rule_violations ON ca_metadata_dictionary_rule_violations.row_id = " . $this->ops_browse_table_name . '.' . $t_item->primaryKey() . " AND ca_metadata_dictionary_rule_violations.table_num = " . $t_item->tableNum() . "\n\t\t\t\t\t\t\t\t\t\t\tINNER JOIN ca_metadata_dictionary_rules ON ca_metadata_dictionary_rules.rule_id = ca_metadata_dictionary_rule_violations.rule_id\n\t\t\t\t\t\t\t\t\t\t\t{$vs_relative_to_join}\n\t\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t\t(ca_metadata_dictionary_rules.rule_code = ?)";
                                 $qr_res = $this->opo_db->query($vs_sql, $vn_row_id);
                             }
                             $va_acc[$vn_i] = $qr_res->getAllFieldValues($this->ops_browse_table_name . '.' . $t_item->primaryKey());
                             $vn_i++;
                         }
                         break;
                         # -----------------------------------------------------
                     # -----------------------------------------------------
                     case 'checkouts':
                         $vs_field_name = $va_facet_info['field'];
                         $vs_table_name = $this->ops_browse_table_name;
                         if ($va_facet_info['relative_to']) {
                             if ($va_relative_execute_sql_data = $this->_getRelativeExecuteSQLData($va_facet_info['relative_to'], $pa_options)) {
                                 $va_relative_to_join = $va_relative_execute_sql_data['relative_joins'];
                                 $vs_relative_to_join = join("\n", $va_relative_to_join);
                                 $vs_table_name = $vs_target_browse_table_name = $va_relative_execute_sql_data['target_table_name'];
                                 $vs_target_browse_table_num = $va_relative_execute_sql_data['target_table_num'];
                                 $vs_target_browse_table_pk = $va_relative_execute_sql_data['target_table_pk'];
                             }
                         }
                         $vs_where = null;
                         $vn_current_time = time();
                         foreach ($va_row_ids as $vn_row_id) {
                             $vs_checkout_join_sql = "INNER JOIN ca_object_checkouts ON ca_object_checkouts.object_id = ca_objects.object_id";
                             $vs_status_code = isset($va_facet_info['status']) && $va_facet_info['status'] ? $va_facet_info['status'] : $vn_row_id;
                             switch ($vs_status_code) {
                                 case 'overdue':
                                     $vs_where = "((ca_object_checkouts.checkout_date <= {$vn_current_time}) AND (ca_object_checkouts.return_date IS NULL) AND (ca_object_checkouts.due_date <= {$vn_current_time}))";
                                     break;
                                 case 'reserved':
                                     $vs_where = "((ca_object_checkouts.checkout_date IS NULL) AND (ca_object_checkouts.return_date IS NULL))";
                                     break;
                                 case 'available':
                                     $vs_checkout_join_sql = '';
                                     $vs_where = "(ca_objects.object_id NOT IN (SELECT object_id FROM ca_object_checkouts WHERE (ca_object_checkouts.checkout_date <= {$vn_current_time}) AND (ca_object_checkouts.return_date IS NULL)))";
                                     break;
                                 case 'all':
                                     $vs_where = "(ca_object_checkouts.checkout_date <= {$vn_current_time})";
                                     break;
                                 default:
                                 case 'out':
                                     $vs_where = "((ca_object_checkouts.checkout_date <= {$vn_current_time}) AND (ca_object_checkouts.return_date IS NULL))";
                                     break;
                             }
                             $vs_sql = "\n\t\t\t\t\t\t\t\t\t\tSELECT ca_objects.object_id\n\t\t\t\t\t\t\t\t\t\tFROM ca_objects\n\t\t\t\t\t\t\t\t\t\t{$vs_checkout_join_sql}\n\t\t\t\t\t\t\t\t\t\tWHERE\n\t\t\t\t\t\t\t\t\t\t\t{$vs_where}\n\t\t\t\t\t\t\t\t\t";
                             $vs_user_sql = null;
                             $va_params = array();
                             switch ($va_facet_info['mode']) {
                                 case 'user':
                                     foreach ($va_row_ids as $vn_index => $vn_row_id) {
                                         $va_row_ids[$vn_index] = (int) $vn_row_id;
                                     }
                                     $va_params[] = $va_row_ids;
                                     $vs_user_sql .= " AND (ca_object_checkouts.user_id IN (?))";
                                     break;
                                 case 'all':
                                 default:
                                     // noop
                                     break;
                             }
                             $qr_res = $this->opo_db->query($vs_sql . $vs_user_sql, $va_params);
                             $va_acc[$vn_i] = $qr_res->getAllFieldValues('ca_objects.object_id');
                             $vn_i++;
                         }
                         break;
                         # -----------------------------------------------------
                     # -----------------------------------------------------
                     default:
                         // handle "search" criteria - search engine queries that can be browsed
                         if ($vs_facet_name === '_search') {
                             if (!($o_search = caGetSearchInstance($this->ops_browse_table_name))) {
                                 $this->postError(2900, _t("Invalid search type"), "BrowseEngine->execute()");
                                 break;
                             }
                             $vs_pk = $t_item->primaryKey();
                             if (is_array($va_type_ids = $this->getTypeRestrictionList()) && sizeof($va_type_ids)) {
                                 $o_search->setTypeRestrictions($va_type_ids);
                             }
                             if (is_array($va_source_ids = $this->getSourceRestrictionList()) && sizeof($va_source_ids)) {
                                 $o_search->setSourceRestrictions($va_source_ids);
                             }
                             $va_options = $pa_options;
                             unset($va_options['sort']);
                             // browse engine takes care of sort so there is no reason to waste time having the search engine do so
                             $va_options['filterNonPrimaryRepresentations'] = true;
                             // filter out non-primary representations in ca_objects results to save (a bit) of time
                             $o_search->setOption('strictPhraseSearching', caGetOption('strictPhraseSearching', $va_options, true));
                             $qr_res = $o_search->search($va_row_ids[0], $va_options);
                             if ($qr_res->numHits() > 0) {
                                 $va_acc[$vn_i] = $qr_res->getPrimaryKeyValues();
                             }
                             $vn_i++;
                         } else {
                             $this->postError(2900, _t("Invalid criteria type"), "BrowseEngine->execute()");
                         }
                         break;
                         # -----------------------------------------------------
                 }
             }
             foreach ($va_acc as $vn_i => $va_hits) {
                 $va_acc[$vn_i] = array_flip($va_hits);
             }
             $vn_smallest_list_index = null;
             foreach ($va_acc as $vn_i => $va_hits) {
                 if (is_null($vn_smallest_list_index)) {
                     $vn_smallest_list_index = $vn_i;
                     continue;
                 }
                 if (sizeof($va_hits) < sizeof($va_acc[$vn_smallest_list_index])) {
                     $vn_smallest_list_index = $vn_i;
                 }
             }
             $va_res = array();
             $va_acc_indices = array_keys($va_acc);
             if (is_array($va_acc[$vn_smallest_list_index])) {
                 foreach ($va_acc[$vn_smallest_list_index] as $vn_row_id => $vb_dummy) {
                     foreach ($va_acc_indices as $vn_i) {
                         if ($vn_i == $vn_smallest_list_index) {
                             continue;
                         }
                         if (!isset($va_acc[$vn_i][$vn_row_id])) {
                             continue 2;
                         }
                     }
                     $va_res[$vn_row_id] = true;
                 }
             }
             if (sizeof($va_res)) {
                 $vs_filter_join_sql = $vs_filter_where_sql = '';
                 $va_wheres = array();
                 $va_joins = array();
                 $vs_sql_distinct = '';
                 if (sizeof($this->opa_result_filters)) {
                     $va_tmp = array();
                     foreach ($this->opa_result_filters as $va_filter) {
                         $vm_val = $this->_filterValueToQueryValue($va_filter);
                         $va_wheres[] = $this->ops_browse_table_name . '.' . $va_filter['field'] . " " . $va_filter['operator'] . " " . $vm_val;
                     }
                 }
                 if (isset($pa_options['checkAccess']) && is_array($pa_options['checkAccess']) && sizeof($pa_options['checkAccess']) && $t_item->hasField('access')) {
                     $va_wheres[] = "(" . $this->ops_browse_table_name . ".access IN (" . join(',', $pa_options['checkAccess']) . "))";
                 }
                 if ((!isset($pa_options['showDeleted']) || !$pa_options['showDeleted']) && $t_item->hasField('deleted')) {
                     $va_wheres[] = "(" . $this->ops_browse_table_name . ".deleted = 0)";
                 }
                 if (isset($pa_options['limitToModifiedOn']) && $pa_options['limitToModifiedOn']) {
                     $o_tep = new TimeExpressionParser();
                     if ($o_tep->parse($pa_options['limitToModifiedOn'])) {
                         $va_range = $o_tep->getUnixTimestamps();
                         $va_joins['ca_change_log_subjects'] = "INNER JOIN ca_change_log_subjects ON ca_change_log_subjects.subject_row_id = " . $this->ops_browse_table_name . "." . $t_item->primaryKey() . " AND ca_change_log_subjects.subject_table_num = " . $t_item->tableNum();
                         $va_joins['ca_change_log'] = "INNER JOIN ca_change_log ON ca_change_log.log_id = ca_change_log_subjects.log_id";
                         $va_wheres[] = "(((ca_change_log.log_datetime BETWEEN " . (int) $va_range['start'] . " AND " . (int) $va_range['end'] . ") AND (ca_change_log.changetype IN ('I', 'U', 'D'))))";
                         $vs_sql_distinct = 'DISTINCT';
                         // need to pull distinct rows since joining the change log can cause dupes
                     }
                 }
                 if (($va_browse_type_ids = $this->getTypeRestrictionList()) && sizeof($va_browse_type_ids)) {
                     $t_subject = $this->getSubjectInstance();
                     $va_wheres[] = '(' . $this->ops_browse_table_name . '.' . $t_subject->getTypeFieldName() . ' IN (' . join(', ', $va_browse_type_ids) . ')' . ($t_subject->getFieldInfo('type_id', 'IS_NULL') ? " OR (" . $this->ops_browse_table_name . '.' . $t_subject->getTypeFieldName() . " IS NULL)" : '') . ')';
                 }
                 if (is_array($va_browse_source_ids) && sizeof($va_browse_source_ids)) {
                     $va_wheres[] = '(' . $this->ops_browse_table_name . '.' . $t_subject->getSourceFieldName() . ' IN (' . join(', ', $va_browse_source_ids) . ') OR (' . $this->ops_browse_table_name . '.' . $t_subject->getSourceFieldName() . ' IS NULL))';
                 }
                 $vs_filter_where_sql = "WHERE (" . $this->ops_browse_table_name . "." . $t_item->primaryKey() . " IN (?)) ";
                 if (sizeof($va_wheres)) {
                     $vs_filter_where_sql .= ' AND (' . join(' AND ', $va_wheres) . ')';
                 }
                 if (sizeof($va_joins)) {
                     $vs_filter_join_sql = join("\n", $va_joins);
                 }
                 $qr_res = $this->opo_db->query("\n\t\t\t\t\t\t\tSELECT {$vs_sql_distinct} " . $this->ops_browse_table_name . "." . $t_item->primaryKey() . "\n\t\t\t\t\t\t\tFROM " . $this->ops_browse_table_name . "\n\t\t\t\t\t\t\t{$vs_filter_join_sql}\n\t\t\t\t\t\t\t{$vs_filter_where_sql}\n\t\t\t\t\t\t", array(array_keys($va_res)));
                 $va_results = $qr_res->getAllFieldValues($t_item->primaryKey());
                 if ((!isset($pa_options['dontFilterByACL']) || !$pa_options['dontFilterByACL']) && $this->opo_config->get('perform_item_level_access_checking') && method_exists($t_item, "supportsACL") && $t_item->supportsACL()) {
                     $va_results = $this->filterHitsByACL($va_results, $this->opn_browse_table_num, $vn_user_id, __CA_ACL_READONLY_ACCESS__);
                 }
                 $this->opo_ca_browse_cache->setResults($va_results);
                 $vb_need_to_save_in_cache = true;
             } else {
                 // No results for some reason - we're here because we don't want to throw a SQL error
                 $this->opo_ca_browse_cache->setResults($va_results = array());
                 $vb_need_to_save_in_cache = true;
             }
         }
     } else {
         // no criteria - don't try to find anything unless configured to do so
         $va_settings = $this->opo_ca_browse_config->getAssoc($this->ops_browse_table_name);
         if (isset($va_settings['show_all_for_no_criteria_browse']) && $va_settings['show_all_for_no_criteria_browse'] || isset($pa_options['showAllForNoCriteriaBrowse']) && $pa_options['showAllForNoCriteriaBrowse']) {
             $va_wheres = $va_joins = array();
             $vs_pk = $t_item->primaryKey();
             if (isset($pa_options['checkAccess']) && is_array($pa_options['checkAccess']) && sizeof($pa_options['checkAccess']) && $t_item->hasField('access')) {
                 $va_wheres[] = "(" . $this->ops_browse_table_name . ".access IN (" . join(',', $pa_options['checkAccess']) . "))";
             }
             if ((!isset($pa_options['showDeleted']) || !$pa_options['showDeleted']) && $t_item->hasField('deleted')) {
                 $va_wheres[] = "(" . $this->ops_browse_table_name . ".deleted = 0)";
             }
             if (isset($pa_options['limitToModifiedOn']) && $pa_options['limitToModifiedOn']) {
                 $o_tep = new TimeExpressionParser();
                 if ($o_tep->parse($pa_options['limitToModifiedOn'])) {
                     $va_range = $o_tep->getUnixTimestamps();
                     $va_joins['ca_change_log_subjects'] = "INNER JOIN ca_change_log_subjects ON ca_change_log_subjects.subject_row_id = " . $this->ops_browse_table_name . ".{$vs_pk} AND ca_change_log_subjects.subject_table_num = " . $t_item->tableNum();
                     $va_joins['ca_change_log'] = "INNER JOIN ca_change_log ON ca_change_log.log_id = ca_change_log_subjects.log_id";
                     $va_wheres[] = "(((ca_change_log.log_datetime BETWEEN " . (int) $va_range['start'] . " AND " . (int) $va_range['end'] . ") AND (ca_change_log.changetype IN ('I', 'U', 'D'))))";
                     $vs_sql_distinct = 'DISTINCT';
                     // need to pull distinct rows since joining the change log can cause dupes
                 }
             }
             $va_browse_type_ids = $this->getTypeRestrictionList();
             $va_browse_source_ids = $this->getSourceRestrictionList();
             if (is_array($va_browse_type_ids) && sizeof($va_browse_type_ids) || is_array($va_browse_source_ids) && sizeof($va_browse_source_ids)) {
                 $t_subject = $this->getSubjectInstance();
                 if (is_array($va_browse_type_ids) && sizeof($va_browse_type_ids)) {
                     $va_wheres[] = '(' . $this->ops_browse_table_name . '.' . $t_subject->getTypeFieldName() . ' IN (' . join(', ', $va_browse_type_ids) . ')' . ($t_subject->getFieldInfo('type_id', 'IS_NULL') ? " OR (" . $this->ops_browse_table_name . '.' . $t_subject->getTypeFieldName() . " IS NULL)" : '') . ')';
                 }
                 if (is_array($va_browse_source_ids) && sizeof($va_browse_source_ids)) {
                     $va_wheres[] = '(' . $this->ops_browse_table_name . '.' . $t_subject->getSourceFieldName() . ' IN (' . join(', ', $va_browse_source_ids) . ') OR (' . $this->ops_browse_table_name . '.' . $t_subject->getSourceFieldName() . ' IS NULL))';
                 }
             }
             if (sizeof($va_wheres)) {
                 $vs_filter_where_sql = 'WHERE ' . join(' AND ', $va_wheres);
             }
             if (sizeof($va_joins)) {
                 $vs_filter_join_sql = join("\n", $va_joins);
             }
             $qr_res = $this->opo_db->query("\n\t\t\t\t\t\tSELECT {$vs_pk}\n\t\t\t\t\t\tFROM " . $t_item->tableName() . "\n\t\t\t\t\t\t{$vs_filter_join_sql}\n\t\t\t\t\t\t{$vs_filter_where_sql}\n\t\t\t\t\t\tORDER BY\n\t\t\t\t\t\t\t{$vs_pk}\n\t\t\t\t\t");
             $va_results = $qr_res->getAllFieldValues($vs_pk);
             if ((!isset($pa_options['dontFilterByACL']) || !$pa_options['dontFilterByACL']) && $this->opo_config->get('perform_item_level_access_checking') && method_exists($t_item, "supportsACL") && $t_item->supportsACL()) {
                 $va_results = array_keys($this->filterHitsByACL($va_results, $this->opn_browse_table_num, $vn_user_id, __CA_ACL_READONLY_ACCESS__));
             }
             $this->opo_ca_browse_cache->setResults($va_results);
         } else {
             $this->opo_ca_browse_cache->setResults(array());
         }
         $vb_need_to_save_in_cache = true;
     }
     if ($vb_need_to_cache_facets && !$pa_options['dontCheckFacetAvailability']) {
         $this->loadFacetContent($pa_options);
     }
     if ($vb_need_to_save_in_cache) {
         $this->opo_ca_browse_cache->save();
     }
     return true;
 }
コード例 #7
0
ファイル: ElasticSearch.php プロジェクト: kai-iak/pawtucket2
 public function search($pn_subject_tablenum, $ps_search_expression, $pa_filters = array(), $po_rewritten_query = null)
 {
     $vn_i = 0;
     $va_old_signs = $po_rewritten_query->getSigns();
     $va_terms = $va_signs = array();
     foreach ($po_rewritten_query->getSubqueries() as $o_lucene_query_element) {
         switch ($vs_class = get_class($o_lucene_query_element)) {
             case 'Zend_Search_Lucene_Search_Query_Term':
             case 'Zend_Search_Lucene_Search_Query_MultiTerm':
             case 'Zend_Search_Lucene_Search_Query_Phrase':
                 $vs_access_point = null;
                 if ($vs_class != 'Zend_Search_Lucene_Search_Query_Term') {
                     $va_raw_terms = array();
                     foreach ($o_lucene_query_element->getQueryTerms() as $o_term) {
                         if (!$vs_access_point && ($vs_field = $o_term->field)) {
                             $vs_access_point = $vs_field;
                         }
                         $va_raw_terms[] = $vs_text = (string) $o_term->text;
                     }
                     $vs_term = join(" ", $va_raw_terms);
                 } else {
                     $vs_access_point = $o_lucene_query_element->getTerm()->field;
                     $vs_term = $o_lucene_query_element->getTerm()->text;
                     $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term('"' . $vs_term . '"', $vs_access_point));
                 }
                 if ($vs_access_point) {
                     list($vs_table, $vs_field, $vs_sub_field) = explode('.', $vs_access_point);
                     if (in_array($vs_table, array('created', 'modified'))) {
                         if (!$this->opo_tep->parse($vs_term)) {
                             break;
                         }
                         $vn_user_id = null;
                         if ($vs_field = trim($vs_field)) {
                             if (!is_int($vs_field)) {
                                 $t_user = new ca_users();
                                 if ($t_user->load(array("user_name" => $vs_field))) {
                                     $vn_user_id = (int) $t_user->getPrimaryKey();
                                 }
                             } else {
                                 $vn_user_id = (int) $vs_field;
                             }
                         }
                         switch ($vs_table) {
                             case 'created':
                                 if ($vn_user_id) {
                                     $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Boolean(array(new Zend_Search_Lucene_Index_Term('[' . $this->opo_tep->getText(array('start_as_iso8601' => true)) . " TO " . $this->opo_tep->getText(array('end_as_iso8601' => true)) . ']', 'created'), new Zend_Search_Lucene_Index_Term($vn_user_id, 'created_user_id')), array(true, true));
                                 } else {
                                     $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term('[' . $this->opo_tep->getText(array('start_as_iso8601' => true)) . " TO " . $this->opo_tep->getText(array('end_as_iso8601' => true)) . ']', 'created'));
                                 }
                                 break;
                             case 'modified':
                                 if ($vn_user_id) {
                                     $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Boolean(array(new Zend_Search_Lucene_Index_Term('[' . $this->opo_tep->getText(array('start_as_iso8601' => true)) . " TO " . $this->opo_tep->getText(array('end_as_iso8601' => true)) . ']', 'modified'), new Zend_Search_Lucene_Index_Term($vn_user_id, 'modified_user_id')), array(true, true));
                                 } else {
                                     $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term('[' . $this->opo_tep->getText(array('start_as_iso8601' => true)) . " TO " . $this->opo_tep->getText(array('end_as_iso8601' => true)) . ']', 'modified'));
                                 }
                                 break;
                         }
                     } else {
                         if ($vs_table && $vs_field) {
                             $t_table = $this->opo_datamodel->getInstanceByTableName($vs_table, true);
                             if (!$t_table) {
                                 break;
                             }
                             $vs_fld_num = $this->opo_datamodel->getFieldNum($vs_table, $vs_field);
                             if (!$vs_fld_num) {
                                 // probably attribute
                                 $t_element = new ca_metadata_elements();
                                 if ($t_element->load(array('element_code' => $vs_sub_field ? $vs_sub_field : $vs_field))) {
                                     //
                                     // For certain types of attributes we can directly query the
                                     // attributes in the database rather than using the full text index
                                     // This allows us to do "intelligent" querying... for example on date ranges
                                     // parsed from natural language input and for length dimensions using unit conversion
                                     //
                                     switch ($t_element->get('datatype')) {
                                         case 2:
                                             // dates
                                             $vb_exact = $vs_term[0] == "#" ? true : false;
                                             // dates prepended by "#" are considered "exact" or "contained - the matched dates must be wholly contained by the search term
                                             if ($vb_exact) {
                                                 if ($this->opo_tep->parse($vs_term)) {
                                                     // TODO: fix date handling to reflect distinctions in ranges
                                                     $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term('[' . $this->opo_tep->getText(array('start_as_iso8601' => true)) . " TO " . $this->opo_tep->getText(array('end_as_iso8601' => true)) . ']', $vs_access_point));
                                                 }
                                             } else {
                                                 if ($this->opo_tep->parse($vs_term)) {
                                                     // TODO: fix date handling to reflect distinctions in ranges
                                                     $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term('[' . $this->opo_tep->getText(array('start_as_iso8601' => true)) . " TO " . $this->opo_tep->getText(array('end_as_iso8601' => true)) . ']', $vs_access_point));
                                                 }
                                             }
                                             break;
                                         case 4:
                                             // geocode
                                             $t_geocode = new GeocodeAttributeValue();
                                             if ($va_coords = caParseGISSearch($vs_term)) {
                                                 $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term('[' . $va_coords['min_latitude'] . ',' . $va_coords['min_longitude'] . " TO " . $va_coords['max_latitude'] . ',' . $va_coords['max_longitude'] . ']', $vs_access_point));
                                             }
                                             break;
                                         case 6:
                                             // currency
                                             $t_cur = new CurrencyAttributeValue();
                                             $va_parsed_value = $t_cur->parseValue($vs_term, $t_element->getFieldValuesArray());
                                             $vn_amount = (double) $va_parsed_value['value_decimal1'];
                                             $vs_currency = preg_replace('![^A-Z0-9]+!', '', $va_parsed_value['value_longtext1']);
                                             $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term($vn_amount, $vs_access_point));
                                             break;
                                         case 8:
                                             // length
                                             $t_len = new LengthAttributeValue();
                                             $va_parsed_value = $t_len->parseValue($vs_term, $t_element->getFieldValuesArray());
                                             $vn_len = (double) $va_parsed_value['value_decimal1'];
                                             // this is always in meters so we can compare this value to the one in the database
                                             $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term($vn_len, $vs_access_point));
                                             break;
                                         case 9:
                                             // weight
                                             $t_weight = new WeightAttributeValue();
                                             $va_parsed_value = $t_weight->parseValue($vs_term, $t_element->getFieldValuesArray());
                                             $vn_weight = (double) $va_parsed_value['value_decimal1'];
                                             // this is always in kilograms so we can compare this value to the one in the database
                                             $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term($vn_weight, $vs_access_point));
                                             break;
                                         case 10:
                                             // timecode
                                             $t_timecode = new TimecodeAttributeValue();
                                             $va_parsed_value = $t_timecode->parseValue($vs_term, $t_element->getFieldValuesArray());
                                             $vn_timecode = (double) $va_parsed_value['value_decimal1'];
                                             $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term($vn_timecode, $vs_access_point));
                                             break;
                                         case 11:
                                             // integer
                                             $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term((double) $vs_term, $vs_access_point));
                                             break;
                                         case 12:
                                             // decimal
                                             $o_lucene_query_element = new Zend_Search_Lucene_Search_Query_Term(new Zend_Search_Lucene_Index_Term((double) $vs_term, $vs_access_point));
                                             break;
                                     }
                                 }
                             }
                         }
                     }
                 }
                 break;
         }
         $va_terms[] = $o_lucene_query_element;
         $va_signs[] = is_array($va_old_signs) ? array_key_exists($vn_i, $va_old_signs) ? $va_old_signs[$vn_i] : true : true;
         $vn_i++;
     }
     $o_rewritten_query = new Zend_Search_Lucene_Search_Query_Boolean($va_terms, $va_signs);
     $ps_search_expression = $this->_queryToString($o_rewritten_query);
     if ($vs_filter_query = $this->_filterValueToQueryValue($pa_filters)) {
         $ps_search_expression = "({$ps_search_expression}) AND ({$vs_filter_query})";
     }
     $vo_http_client = new Zend_Http_Client();
     $vo_http_client->setUri($this->ops_elasticsearch_base_url . "/" . $this->ops_elasticsearch_index_name . "/" . $this->opo_datamodel->getTableName($pn_subject_tablenum) . "/" . "_search");
     if (preg_match_all("!([A-Za-z0-9_\\-\\.]+)[/]{1}([A-Za-z0-9_\\-]+):(\"[^\"]*\")!", $ps_search_expression, $va_matches) || preg_match_all("!([A-Za-z0-9_\\-\\.]+)[/]{1}([A-Za-z0-9_\\-]+):([^ ]*)!", $ps_search_expression, $va_matches)) {
         foreach ($va_matches[0] as $vn_i => $vs_element) {
             $vs_fld = $va_matches[1][$vn_i];
             if (!($vs_rel_type = trim($va_matches[2][$vn_i]))) {
                 continue;
             }
             $va_tmp = explode(".", $vs_fld);
             $vs_rel_table = caGetRelationshipTableName($pn_subject_tablenum, $va_tmp[0]);
             $va_rel_type_ids = $vs_rel_type && $vs_rel_table ? caMakeRelationshipTypeIDList($vs_rel_table, array($vs_rel_type)) : null;
             $va_new_elements = array();
             foreach ($va_rel_type_ids as $vn_rel_type_id) {
                 $va_new_elements[] = "(" . $va_matches[1][$vn_i] . "/" . $vn_rel_type_id . ":" . $va_matches[3][$vn_i] . ")";
             }
             $ps_search_expression = str_replace($vs_element, "(" . join(" OR ", $va_new_elements) . ")", $ps_search_expression);
         }
     }
     $ps_search_expression = str_replace("/", '\\/', $ps_search_expression);
     // escape forward slashes used to delimit relationship type qualifier
     Debug::msg("[ElasticSearch] Running query {$ps_search_expression}");
     $vo_http_client->setParameterGet(array('size' => intval($this->opa_options["limit"]), 'q' => $ps_search_expression, 'fields' => ''));
     $vo_http_response = $vo_http_client->request();
     $va_result = json_decode($vo_http_response->getBody(), true);
     return new WLPlugSearchEngineElasticSearchResult($va_result["hits"]["hits"], $pn_subject_tablenum);
 }
コード例 #8
0
ファイル: SqlSearch.php プロジェクト: ymani2435/providence
 /**
  *
  *
  * @param int $pn_subject_tablenum
  * @param array $pa_subject_row_ids
  * @param int $pn_content_tablenum
  * @param string $ps_content_fieldnum
  * @param int $pn_content_row_id
  * @param string $ps_content
  * @param array $pa_options
  *		literalContent = array of text content to be applied without tokenization
  *		BOOST = Indexing boost to apply
  *		PRIVATE = Set indexing to private
  */
 public function updateIndexingInPlace($pn_subject_tablenum, $pa_subject_row_ids, $pn_content_tablenum, $ps_content_fieldnum, $pn_content_row_id, $ps_content, $pa_options = null)
 {
     // Find existing indexing for this subject and content
     foreach ($pa_subject_row_ids as $vn_subject_row_id) {
         $this->removeRowIndexing($pn_subject_tablenum, $vn_subject_row_id, $pn_content_tablenum, $ps_content_fieldnum, $pn_content_row_id);
     }
     if (caGetOption("DONT_TOKENIZE", $pa_options, false) || in_array('DONT_TOKENIZE', $pa_options)) {
         $va_words = array($ps_content);
     } else {
         $va_words = $this->_tokenize($ps_content);
     }
     if (caGetOption("INDEX_AS_IDNO", $pa_options, false) || in_array('INDEX_AS_IDNO', $pa_options)) {
         $t_content = $this->opo_datamodel->getInstanceByTableNum($pn_content_tablenum, true);
         if (method_exists($t_content, "getIDNoPlugInInstance") && ($o_idno = $t_content->getIDNoPlugInInstance())) {
             $va_values = $o_idno->getIndexValues($ps_content);
             $va_words += $va_values;
         }
     }
     $va_literal_content = caGetOption("literalContent", $pa_options, null);
     if ($va_literal_content && !is_array($va_literal_content)) {
         $va_literal_content = array($va_literal_content);
     }
     $vn_boost = 1;
     if (isset($pa_options['BOOST'])) {
         $vn_boost = intval($pa_options['BOOST']);
     }
     if (!isset($pa_options['PRIVATE'])) {
         $pa_options['PRIVATE'] = 0;
     }
     if (in_array('PRIVATE', $pa_options, true)) {
         $pa_options['PRIVATE'] = 1;
     }
     $vn_private = $pa_options['PRIVATE'] ? 1 : 0;
     $vn_rel_type_id = (int) caGetOption('relationship_type_id', $pa_options, 0);
     $va_row_insert_sql = array();
     $pn_subject_tablenum = (int) $pn_subject_tablenum;
     $vn_row_id = (int) $vn_row_id;
     $pn_content_tablenum = (int) $pn_content_tablenum;
     $pn_content_row_id = (int) $pn_content_row_id;
     $vn_boost = (int) $vn_boost;
     $vn_access = (int) $vn_access;
     foreach ($pa_subject_row_ids as $vn_row_id) {
         if (!$vn_row_id) {
             if ($this->debug) {
                 Debug::msg("[SqlSearchDebug] Cannot index row because row id is missing!");
             }
             continue;
         }
         $vn_seq = 0;
         foreach ($va_words as $vs_word) {
             if (!($vn_word_id = $this->getWordID($vs_word))) {
                 continue;
             }
             $va_row_insert_sql[] = "({$pn_subject_tablenum}, {$vn_row_id}, {$pn_content_tablenum}, '{$ps_content_fieldnum}', {$pn_content_row_id}, {$vn_word_id}, {$vn_boost}, {$vn_private}, {$vn_rel_type_id})";
             $vn_seq++;
         }
         if (is_array($va_literal_content)) {
             foreach ($va_literal_content as $vs_literal) {
                 if (!($vn_word_id = $this->getWordID($vs_literal))) {
                     continue;
                 }
                 $va_row_insert_sql[] = "({$pn_subject_tablenum}, {$vn_row_id}, {$pn_content_tablenum}, '{$ps_content_fieldnum}', {$pn_content_row_id}, {$vn_word_id}, {$vn_boost}, {$vn_private}, {$vn_rel_type_id})";
                 $vn_seq++;
             }
         }
     }
     // do insert
     if (sizeof($va_row_insert_sql)) {
         $vs_sql = $this->ops_insert_word_index_sql . "\n" . join(",", $va_row_insert_sql);
         $this->opo_db->query($vs_sql);
         if ($this->debug) {
             Debug::msg("[SqlSearchDebug] Commit row indexing");
         }
     }
 }
コード例 #9
0
ファイル: ca_objects.php プロジェクト: kai-iak/pawtucket2
 /**
  * Return array with list of significant events in object life cycle as configured for 
  * a ca_objects_history editor bundle.
  *
  * @param array $pa_bundle_settings The settings for a ca_objects_history editing BUNDLES
  * @param array $pa_options Array of options. Options include:
  *		noCache = Don't use any cached history data. [Default is false]
  *		currentOnly = Only return history entries dates before or on the current date. [Default is false]
  *		limit = Only return a maximum number of history entries. [Default is null; no limit]
  *
  * @return array A list of life cycle events, indexed by historic timestamp for date of occurrrence. Each list value is an array of history entries.
  *
  * @used-by ca_objects::getObjectHistoryHTMLFormBundle
  */
 public function getObjectHistory($pa_bundle_settings = null, $pa_options = null)
 {
     global $g_ui_locale;
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     if (!is_array($pa_bundle_settings)) {
         $pa_bundle_settings = array();
     }
     $vs_cache_key = caMakeCacheKeyFromOptions(array_merge($pa_bundle_settings, $pa_options, array('object_id' => $this->getPrimaryKey())));
     $pb_no_cache = caGetOption('noCache', $pa_options, false);
     if (!$pb_no_cache && isset(ca_objects::$s_object_use_cache[$vs_cache_key])) {
         return ca_objects::$s_object_use_cache[$vs_cache_key];
     }
     $pb_display_label_only = caGetOption('displayLabelOnly', $pa_options, false);
     $pb_get_current_only = caGetOption('currentOnly', $pa_options, false);
     $pn_limit = caGetOption('limit', $pa_options, null);
     $vs_display_template = caGetOption('display_template', $pa_bundle_settings, _t('No template defined'));
     $vs_history_template = caGetOption('history_template', $pa_bundle_settings, $vs_display_template);
     $vn_current_date = caDateToHistoricTimestamp(_t('now'));
     $o_media_coder = new MediaInfoCoder();
     //
     // Get history
     //
     $va_history = array();
     // Lots
     if (is_array($va_lot_types = caGetOption('ca_object_lots_showTypes', $pa_bundle_settings, null)) && ($vn_lot_id = $this->get('lot_id'))) {
         $t_lot = new ca_object_lots($vn_lot_id);
         if (!$t_lot->get('deleted')) {
             $va_lot_type_info = $t_lot->getTypeList();
             $vn_type_id = $t_lot->get('type_id');
             $vs_color = $va_lot_type_info[$vn_type_id]['color'];
             if (!$vs_color || $vs_color == '000000') {
                 $vs_color = caGetOption("ca_object_lots_{$va_lot_type_info[$vn_type_id]['idno']}_color", $pa_bundle_settings, 'ffffff');
             }
             $va_dates = array();
             $va_date_elements = caGetOption("ca_object_lots_{$va_lot_type_info[$vn_type_id]['idno']}_dateElement", $pa_bundle_settings, null);
             if (!is_array($va_date_elements) && $va_date_elements) {
                 $va_date_elements = array($va_date_elements);
             }
             if (is_array($va_date_elements) && sizeof($va_date_elements)) {
                 foreach ($va_date_elements as $vs_date_element) {
                     $va_dates[] = array('sortable' => $t_lot->get($vs_date_element, array('getDirectDate' => true)), 'display' => $t_lot->get($vs_date_element));
                 }
             }
             if (!sizeof($va_dates)) {
                 $va_dates[] = array('sortable' => $vn_date = caUnixTimestampToHistoricTimestamps($t_lot->getCreationTimestamp(null, array('timestampOnly' => true))), 'display' => caGetLocalizedDate($vn_date));
             }
             foreach ($va_dates as $va_date) {
                 if (!$va_date['sortable']) {
                     continue;
                 }
                 if (!in_array($vn_type_id, $va_lot_types)) {
                     continue;
                 }
                 if ($pb_get_current_only && $va_date['sortable'] > $vn_current_date) {
                     continue;
                 }
                 $vs_default_display_template = '^ca_object_lots.preferred_labels.name (^ca_object_lots.idno_stub)';
                 $vs_display_template = $pb_display_label_only ? "" : caGetOption("ca_object_lots_{$va_lot_type_info[$vn_type_id]['idno']}_displayTemplate", $pa_bundle_settings, $vs_default_display_template);
                 $va_history[$va_date['sortable']][] = array('type' => 'ca_object_lots', 'id' => $vn_lot_id, 'display' => $t_lot->getWithTemplate($vs_display_template), 'color' => $vs_color, 'icon_url' => $vs_icon_url = $o_media_coder->getMediaTag($va_lot_type_info[$vn_type_id]['icon'], 'icon'), 'typename_singular' => $vs_typename = $va_lot_type_info[$vn_type_id]['name_singular'], 'typename_plural' => $va_lot_type_info[$vn_type_id]['name_plural'], 'type_id' => $vn_type_id, 'icon' => '<div class="caUseHistoryIconContainer" style="background-color: #' . $vs_color . '"><div class="caUseHistoryIcon">' . ($vs_icon_url ? $vs_icon_url : '<div class="caUseHistoryIconText">' . $vs_typename . '</div>') . '</div></div>', 'date' => $va_date['display']);
             }
         }
     }
     // Loans
     $va_loans = $this->get('ca_loans.loan_id', array('returnAsArray' => true));
     if (is_array($va_loan_types = caGetOption('ca_loans_showTypes', $pa_bundle_settings, null)) && is_array($va_loans) && sizeof($va_loans)) {
         $qr_loans = caMakeSearchResult('ca_loans', $va_loans);
         $t_loan = new ca_loans();
         $va_loan_type_info = $t_loan->getTypeList();
         $va_date_elements_by_type = array();
         foreach ($va_loan_types as $vn_type_id) {
             if (!is_array($va_date_elements = caGetOption("ca_loans_{$va_loan_type_info[$vn_type_id]['idno']}_dateElement", $pa_bundle_settings, null)) && $va_date_elements) {
                 $va_date_elements = array($va_date_elements);
             }
             if (!$va_date_elements) {
                 continue;
             }
             $va_date_elements_by_type[$vn_type_id] = $va_date_elements;
         }
         while ($qr_loans->nextHit()) {
             $vn_loan_id = $qr_loans->get('loan_id');
             if ((string) $qr_loans->get('ca_loans.deleted') !== '0') {
                 continue;
             }
             // filter out deleted
             $vn_type_id = $qr_loans->get('type_id');
             $va_dates = array();
             if (is_array($va_date_elements_by_type[$vn_type_id]) && sizeof($va_date_elements_by_type[$vn_type_id])) {
                 foreach ($va_date_elements_by_type[$vn_type_id] as $vs_date_element) {
                     $va_dates[] = array('sortable' => $qr_loans->get("ca_loans.{$vs_date_element}", array('getDirectDate' => true)), 'display' => $qr_loans->get("ca_loans.{$vs_date_element}"));
                 }
             }
             if (!sizeof($va_dates)) {
                 $va_dates[] = array('sortable' => $vn_date = caUnixTimestampToHistoricTimestamps($qr_loans->get('lastModified')), 'display' => caGetLocalizedDate($vn_date));
             }
             $vs_default_display_template = '^ca_loans.preferred_labels.name (^ca_loans.idno)';
             $vs_display_template = $pb_display_label_only ? $vs_default_display_template : caGetOption("ca_loans_{$va_loan_type_info[$vn_type_id]['idno']}_displayTemplate", $pa_bundle_settings, $vs_default_display_template);
             foreach ($va_dates as $va_date) {
                 if (!$va_date['sortable']) {
                     continue;
                 }
                 if (!in_array($vn_type_id, $va_loan_types)) {
                     continue;
                 }
                 if ($pb_get_current_only && $va_date['sortable'] > $vn_current_date) {
                     continue;
                 }
                 $vs_color = $va_loan_type_info[$vn_type_id]['color'];
                 if (!$vs_color || $vs_color == '000000') {
                     $vs_color = caGetOption("ca_loans_{$va_loan_type_info[$vn_type_id]['idno']}_color", $pa_bundle_settings, 'ffffff');
                 }
                 $va_history[$va_date['sortable']][] = array('type' => 'ca_loans', 'id' => $vn_loan_id, 'display' => $qr_loans->getWithTemplate($vs_display_template), 'color' => $vs_color, 'icon_url' => $vs_icon_url = $o_media_coder->getMediaTag($va_loan_type_info[$vn_type_id]['icon'], 'icon'), 'typename_singular' => $vs_typename = $va_loan_type_info[$vn_type_id]['name_singular'], 'typename_plural' => $va_loan_type_info[$vn_type_id]['name_plural'], 'type_id' => $vn_type_id, 'icon' => '<div class="caUseHistoryIconContainer" style="background-color: #' . $vs_color . '"><div class="caUseHistoryIcon">' . ($vs_icon_url ? $vs_icon_url : '<div class="caUseHistoryIconText">' . $vs_typename . '</div>') . '</div></div>', 'date' => $va_date['display']);
             }
         }
     }
     // Movements
     $va_movements = $this->get('ca_movements.movement_id', array('returnAsArray' => true));
     if (is_array($va_movement_types = caGetOption('ca_movements_showTypes', $pa_bundle_settings, null)) && is_array($va_movements) && sizeof($va_movements)) {
         $qr_movements = caMakeSearchResult('ca_movements', $va_movements);
         $t_movement = new ca_movements();
         $va_movement_type_info = $t_movement->getTypeList();
         $va_date_elements_by_type = array();
         foreach ($va_movement_types as $vn_type_id) {
             if (!is_array($va_date_elements = caGetOption("ca_movements_{$va_movement_type_info[$vn_type_id]['idno']}_dateElement", $pa_bundle_settings, null)) && $va_date_elements) {
                 $va_date_elements = array($va_date_elements);
             }
             if (!$va_date_elements) {
                 continue;
             }
             $va_date_elements_by_type[$vn_type_id] = $va_date_elements;
         }
         while ($qr_movements->nextHit()) {
             $vn_movement_id = $qr_movements->get('movement_id');
             if ((string) $qr_movements->get('ca_movements.deleted') !== '0') {
                 continue;
             }
             // filter out deleted
             $vn_type_id = $qr_movements->get('type_id');
             $va_dates = array();
             if (is_array($va_date_elements_by_type[$vn_type_id]) && sizeof($va_date_elements_by_type[$vn_type_id])) {
                 foreach ($va_date_elements_by_type[$vn_type_id] as $vs_date_element) {
                     $va_dates[] = array('sortable' => $qr_movements->get("ca_movements.{$vs_date_element}", array('getDirectDate' => true)), 'display' => $qr_movements->get("ca_movements.{$vs_date_element}"));
                 }
             }
             if (!sizeof($va_dates)) {
                 $va_dates[] = array('sortable' => $vn_date = caUnixTimestampToHistoricTimestamps($qr_movements->get('lastModified')), 'display' => caGetLocalizedDate($vn_date));
             }
             $vs_default_display_template = '^ca_movements.preferred_labels.name (^ca_movements.idno)';
             $vs_display_template = $pb_display_label_only ? $vs_default_display_template : caGetOption("ca_movements_{$va_movement_type_info[$vn_type_id]['idno']}_displayTemplate", $pa_bundle_settings, $vs_default_display_template);
             foreach ($va_dates as $va_date) {
                 if (!$va_date['sortable']) {
                     continue;
                 }
                 if (!in_array($vn_type_id, $va_movement_types)) {
                     continue;
                 }
                 if ($pb_get_current_only && $va_date['sortable'] > $vn_current_date) {
                     continue;
                 }
                 $vs_color = $va_movement_type_info[$vn_type_id]['color'];
                 if (!$vs_color || $vs_color == '000000') {
                     $vs_color = caGetOption("ca_movements_{$va_movement_type_info[$vn_type_id]['idno']}_color", $pa_bundle_settings, 'ffffff');
                 }
                 $va_history[$va_date['sortable']][] = array('type' => 'ca_movements', 'id' => $vn_movement_id, 'display' => $qr_movements->getWithTemplate($vs_display_template), 'color' => $vs_color, 'icon_url' => $vs_icon_url = $o_media_coder->getMediaTag($va_movement_type_info[$vn_type_id]['icon'], 'icon'), 'typename_singular' => $vs_typename = $va_movement_type_info[$vn_type_id]['name_singular'], 'typename_plural' => $va_movement_type_info[$vn_type_id]['name_plural'], 'type_id' => $vn_type_id, 'icon' => '<div class="caUseHistoryIconContainer" style="background-color: #' . $vs_color . '"><div class="caUseHistoryIcon">' . ($vs_icon_url ? $vs_icon_url : '<div class="caUseHistoryIconText">' . $vs_typename . '</div>') . '</div></div>', 'date' => $va_date['display']);
             }
         }
     }
     // Occurrences
     $va_occurrences = $this->get('ca_occurrences.occurrence_id', array('returnAsArray' => true));
     if (is_array($va_occurrence_types = caGetOption('ca_occurrences_showTypes', $pa_bundle_settings, null)) && is_array($va_occurrences) && sizeof($va_occurrences)) {
         $qr_occurrences = caMakeSearchResult('ca_occurrences', $va_occurrences);
         $t_occurrence = new ca_occurrences();
         $va_occurrence_type_info = $t_occurrence->getTypeList();
         $va_date_elements_by_type = array();
         foreach ($va_occurrence_types as $vn_type_id) {
             if (!is_array($va_date_elements = caGetOption("ca_occurrences_{$va_occurrence_type_info[$vn_type_id]['idno']}_dateElement", $pa_bundle_settings, null)) && $va_date_elements) {
                 $va_date_elements = array($va_date_elements);
             }
             if (!$va_date_elements) {
                 continue;
             }
             $va_date_elements_by_type[$vn_type_id] = $va_date_elements;
         }
         while ($qr_occurrences->nextHit()) {
             $vn_occurrence_id = $qr_occurrences->get('occurrence_id');
             if ((string) $qr_occurrences->get('ca_occurrences.deleted') !== '0') {
                 continue;
             }
             // filter out deleted
             $vn_type_id = $qr_occurrences->get('type_id');
             $va_dates = array();
             if (is_array($va_date_elements_by_type[$vn_type_id]) && sizeof($va_date_elements_by_type[$vn_type_id])) {
                 foreach ($va_date_elements_by_type[$vn_type_id] as $vs_date_element) {
                     $va_dates[] = array('sortable' => $qr_occurrences->get("ca_occurrences.{$vs_date_element}", array('getDirectDate' => true)), 'display' => $qr_occurrences->get("ca_occurrences.{$vs_date_element}"));
                 }
             }
             if (!sizeof($va_dates)) {
                 $va_dates[] = array('sortable' => $vn_date = caUnixTimestampToHistoricTimestamps($qr_occurrences->get('lastModified')), 'display' => caGetLocalizedDate($vn_date));
             }
             $vs_default_display_template = '^ca_occurrences.preferred_labels.name (^ca_occurrences.idno)';
             $vs_display_template = $pb_display_label_only ? $vs_default_display_template : caGetOption("ca_occurrences_{$va_occurrence_type_info[$vn_type_id]['idno']}_displayTemplate", $pa_bundle_settings, $vs_default_display_template);
             foreach ($va_dates as $va_date) {
                 if (!$va_date['sortable']) {
                     continue;
                 }
                 if (!in_array($vn_type_id, $va_occurrence_types)) {
                     continue;
                 }
                 if ($pb_get_current_only && $va_date['sortable'] > $vn_current_date) {
                     continue;
                 }
                 $vs_color = $va_occurrence_type_info[$vn_type_id]['color'];
                 if (!$vs_color || $vs_color == '000000') {
                     $vs_color = caGetOption("ca_occurrences_{$va_occurrence_type_info[$vn_type_id]['idno']}_color", $pa_bundle_settings, 'ffffff');
                 }
                 $va_history[$va_date['sortable']][] = array('type' => 'ca_occurrences', 'id' => $vn_occurrence_id, 'display' => $qr_occurrences->getWithTemplate($vs_display_template), 'color' => $vs_color, 'icon_url' => $vs_icon_url = $o_media_coder->getMediaTag($va_occurrence_type_info[$vn_type_id]['icon'], 'icon'), 'typename_singular' => $vs_typename = $va_occurrence_type_info[$vn_type_id]['name_singular'], 'typename_plural' => $va_occurrence_type_info[$vn_type_id]['name_plural'], 'type_id' => $vn_type_id, 'icon' => '<div class="caUseHistoryIconContainer" style="background-color: #' . $vs_color . '"><div class="caUseHistoryIcon">' . ($vs_icon_url ? $vs_icon_url : '<div class="caUseHistoryIconText">' . $vs_typename . '</div>') . '</div></div>', 'date' => $va_date['display']);
             }
         }
     }
     // Storage locations
     $va_locations = $this->get('ca_objects_x_storage_locations.relation_id', array('returnAsArray' => true));
     if (is_array($va_location_types = caGetOption('ca_storage_locations_showRelationshipTypes', $pa_bundle_settings, null)) && is_array($va_locations) && sizeof($va_locations)) {
         $t_location = new ca_storage_locations();
         $va_location_type_info = $t_location->getTypeList();
         $vs_name_singular = $t_location->getProperty('NAME_SINGULAR');
         $vs_name_plural = $t_location->getProperty('NAME_PLURAL');
         $qr_locations = caMakeSearchResult('ca_objects_x_storage_locations', $va_locations);
         $vs_default_display_template = '^ca_storage_locations.parent.preferred_labels.name ➜ ^ca_storage_locations.preferred_labels.name (^ca_storage_locations.idno)';
         $vs_display_template = $pb_display_label_only ? $vs_default_display_template : caGetOption('ca_storage_locations_displayTemplate', $pa_bundle_settings, $vs_default_display_template);
         Debug::msg($qr_locations->numHits());
         while ($qr_locations->nextHit()) {
             $vn_location_id = $qr_locations->get('ca_objects_x_storage_locations.location_id');
             if ((string) $qr_locations->get('ca_storage_locations.deleted') !== '0') {
                 continue;
             }
             // filter out deleted
             $va_date = array('sortable' => $qr_locations->get("ca_objects_x_storage_locations.effective_date", array('getDirectDate' => true)), 'display' => $qr_locations->get("ca_objects_x_storage_locations.effective_date"));
             if (!$va_date['sortable']) {
                 continue;
             }
             if (!in_array($vn_rel_type_id = $qr_locations->get('ca_objects_x_storage_locations.type_id'), $va_location_types)) {
                 continue;
             }
             $vn_type_id = $qr_locations->get('ca_storage_locations.type_id');
             if ($pb_get_current_only && $va_date['sortable'] > $vn_current_date) {
                 continue;
             }
             $vs_color = $va_location_type_info[$vn_type_id]['color'];
             if (!$vs_color || $vs_color == '000000') {
                 $vs_color = caGetOption("ca_storage_locations_color", $pa_bundle_settings, 'ffffff');
             }
             $va_history[$va_date['sortable']][] = array('type' => 'ca_storage_locations', 'id' => $vn_location_id, 'relation_id' => $qr_locations->get('relation_id'), 'display' => $qr_locations->getWithTemplate("<unit relativeTo='ca_storage_locations'>{$vs_display_template}</unit>"), 'color' => $vs_color, 'icon_url' => $vs_icon_url = $o_media_coder->getMediaTag($va_location_type_info[$vn_type_id]['icon'], 'icon'), 'typename_singular' => $vs_name_singular, 'typename_plural' => $vs_name_plural, 'type_id' => $vn_type_id, 'rel_type_id' => $vn_rel_type_id, 'icon' => '<div class="caUseHistoryIconContainer" style="background-color: #' . $vs_color . '"><div class="caUseHistoryIcon">' . ($vs_icon_url ? $vs_icon_url : '<div class="caUseHistoryIconText">' . $vs_name_singular . '</div>') . '</div></div>', 'date' => $va_date['display']);
         }
     }
     // Deaccession
     if ($this->get('is_deaccessioned') && caGetOption('showDeaccessionInformation', $pa_bundle_settings, false)) {
         $vs_color = caGetOption('deaccession_color', $pa_bundle_settings, 'cccccc');
         $vn_date = $this->get('deaccession_date', array('getDirectDate' => true));
         $vs_default_display_template = '^ca_objects.deaccession_notes';
         $vs_display_template = $pb_display_label_only ? $vs_default_display_template : caGetOption('deaccession_displayTemplate', $pa_bundle_settings, $vs_default_display_template);
         if (!($pb_get_current_only && $vn_date > $vn_current_date)) {
             $va_history[$vn_date][] = array('type' => 'ca_objects_deaccession', 'id' => $this->getPrimaryKey(), 'display' => $this->getWithTemplate("<unit>{$vs_display_template}</unit>"), 'color' => $vs_color, 'icon_url' => '', 'typename_singular' => $vs_name_singular = _t('deaccession'), 'typename_plural' => $vs_name_plural = _t('deaccessions'), 'type_id' => null, 'icon' => '<div class="caUseHistoryIconContainer" style="background-color: #' . $vs_color . '"><div class="caUseHistoryIcon"><div class="caUseHistoryIconText">' . $vs_name_singular . '</div>' . '</div></div>', 'date' => $this->get('deaccession_date'));
         }
     }
     ksort($va_history);
     $va_history = array_reverse($va_history);
     if ($pn_limit > 0) {
         $va_history = array_slice($va_history, 0, $pn_limit);
     }
     if (sizeof(ca_objects::$s_object_use_cache[$vs_cache_key]) > 100) {
         ca_objects::$s_object_use_cache[$vs_cache_key] = array_slice(ca_objects::$s_object_use_cache[$vs_cache_key], 0, 50);
     }
     return ca_objects::$s_object_use_cache[$vs_cache_key] = $va_history;
 }
コード例 #10
0
 /**
  * Saves the content of a form editing new or existing records. It returns the same form + status messages rendered into the current view, inherited from ActionController
  *
  * @param array $pa_options Array of options passed through to _initView and saveBundlesForScreen()
  */
 public function Save($pa_options = null)
 {
     list($vn_subject_id, $t_subject, $t_ui, $vn_parent_id, $vn_above_id, $vs_rel_table, $vn_rel_type_id, $vn_rel_id) = $this->_initView($pa_options);
     if (!is_array($pa_options)) {
         $pa_options = array();
     }
     if (!$this->_checkAccess($t_subject)) {
         return false;
     }
     if ($vn_above_id) {
         // Convert "above" id (the id of the record we're going to make the newly created record parent of
         if (($t_instance = $this->opo_datamodel->getInstanceByTableName($this->ops_table_name)) && $t_instance->load($vn_above_id)) {
             $vn_parent_id = $t_instance->get($vs_parent_id_fld = $t_instance->getProperty('HIERARCHY_PARENT_ID_FLD'));
             $this->request->setParameter($vs_parent_id_fld, $vn_parent_id);
             $this->view->setVar('parent_id', $vn_parent_id);
         }
     }
     if (in_array($this->ops_table_name, array('ca_representation_annotations'))) {
         $vs_auth_table_name = 'ca_objects';
     }
     if (!sizeof($_POST)) {
         $this->notification->addNotification(_t("Cannot save using empty request. Are you using a bookmark?"), __NOTIFICATION_TYPE_ERROR__);
         $this->render('screen_html.php');
         return;
     }
     // set "context" id from those editors that need to restrict idno lookups to within the context of another field value (eg. idno's for ca_list_items are only unique within a given list_id)
     $vn_context_id = null;
     if ($vs_idno_context_field = $t_subject->getProperty('ID_NUMBERING_CONTEXT_FIELD')) {
         if ($vn_subject_id > 0) {
             $this->view->setVar('_context_id', $vn_context_id = $t_subject->get($vs_idno_context_field));
         } else {
             if ($vn_parent_id > 0) {
                 $t_parent = $this->opo_datamodel->getInstanceByTableName($this->ops_table_name);
                 if ($t_parent->load($vn_parent_id)) {
                     $this->view->setVar('_context_id', $vn_context_id = $t_parent->get($vs_idno_context_field));
                 }
             }
         }
         if ($vn_context_id) {
             $t_subject->set($vs_idno_context_field, $vn_context_id);
         }
     }
     if (!($vs_type_name = $t_subject->getTypeName())) {
         $vs_type_name = $t_subject->getProperty('NAME_SINGULAR');
     }
     if ($vn_subject_id && !$t_subject->getPrimaryKey()) {
         $this->notification->addNotification(_t("%1 does not exist", $vs_type_name), __NOTIFICATION_TYPE_ERROR__);
         return;
     }
     $vb_is_insert = !$t_subject->getPrimaryKey();
     # trigger "BeforeSaveItem" hook
     $this->opo_app_plugin_manager->hookBeforeSaveItem(array('id' => $vn_subject_id, 'table_num' => $t_subject->tableNum(), 'table_name' => $t_subject->tableName(), 'instance' => $t_subject, 'is_insert' => $vb_is_insert));
     $vb_save_rc = false;
     $va_opts = array_merge($pa_options, array('ui_instance' => $t_ui));
     if ($this->_beforeSave($t_subject, $vb_is_insert)) {
         if ($vb_save_rc = $t_subject->saveBundlesForScreen($this->request->getActionExtra(), $this->request, $va_opts)) {
             $this->_afterSave($t_subject, $vb_is_insert);
         }
     }
     $this->view->setVar('t_ui', $t_ui);
     if (!$vn_subject_id) {
         // this was an insert
         $vn_subject_id = $t_subject->getPrimaryKey();
         if (!$vb_save_rc) {
             // failed insert
             $vs_message = _t("Could not save %1", $vs_type_name);
         } else {
             // ok insert
             $vs_message = _t("Added %1", $vs_type_name);
             $this->request->setParameter($t_subject->primaryKey(), $vn_subject_id, 'GET');
             $this->view->setVar($t_subject->primaryKey(), $vn_subject_id);
             $this->view->setVar('subject_id', $vn_subject_id);
             $this->request->session->setVar($this->ops_table_name . '_browse_last_id', $vn_subject_id);
             // set last edited
             // relate newly created record if requested
             if ($vs_rel_table && $vn_rel_type_id && $vn_rel_id) {
                 if ($this->opo_datamodel->tableExists($vs_rel_table)) {
                     Debug::msg("[Save()] Relating new record using parameters from request: {$vs_rel_table} / {$vn_rel_type_id} / {$vn_rel_id}");
                     $t_subject->addRelationship($vs_rel_table, $vn_rel_id, $vn_rel_type_id);
                 }
             }
             // Set ACL for newly created record
             if ($t_subject->getAppConfig()->get('perform_item_level_access_checking') && !$t_subject->getAppConfig()->get("{$this->ops_table_name}_dont_do_item_level_access_control")) {
                 $t_subject->setACLUsers(array($this->request->getUserID() => __CA_ACL_EDIT_DELETE_ACCESS__));
                 $t_subject->setACLWorldAccess($t_subject->getAppConfig()->get('default_item_access_level'));
             }
             // If "above_id" is set then, we want to load the record pointed to by it and set its' parent to be the newly created record
             // The newly created record's parent is already set to be the current parent of the "above_id"; the net effect of all of this
             // is to insert the newly created record between the "above_id" record and its' current parent.
             if ($vn_above_id && ($t_instance = $this->opo_datamodel->getInstanceByTableName($this->ops_table_name, true)) && $t_instance->load($vn_above_id)) {
                 $t_instance->setMode(ACCESS_WRITE);
                 $t_instance->set('parent_id', $vn_subject_id);
                 $t_instance->update();
                 if ($t_instance->numErrors()) {
                     $this->notification->addNotification($t_instance->getErrorDescription(), __NOTIFICATION_TYPE_ERROR__);
                 }
             }
         }
     } else {
         $vs_message = _t("Saved changes to %1", $vs_type_name);
     }
     $va_errors = $this->request->getActionErrors();
     // all errors from all sources
     $va_general_errors = $this->request->getActionErrors('general');
     // just "general" errors - ones that are not attached to a specific part of the form
     if (is_array($va_general_errors) && sizeof($va_general_errors) > 0) {
         foreach ($va_general_errors as $o_e) {
             $this->notification->addNotification($o_e->getErrorDescription(), __NOTIFICATION_TYPE_ERROR__);
         }
     }
     if (sizeof($va_errors) - sizeof($va_general_errors) > 0) {
         $va_error_list = array();
         $vb_no_save_error = false;
         foreach ($va_errors as $o_e) {
             $va_error_list[$o_e->getErrorDescription()] = "<li>" . $o_e->getErrorDescription() . "</li>\n";
             switch ($o_e->getErrorNumber()) {
                 case 1100:
                     // duplicate/invalid idno
                     if (!$vn_subject_id) {
                         // can't save new record if idno is not valid (when updating everything but idno is saved if it is invalid)
                         $vb_no_save_error = true;
                     }
                     break;
             }
         }
         if ($vb_no_save_error) {
             $this->notification->addNotification(_t("There are errors preventing <strong>ALL</strong> information from being saved. Correct the problems and click \"save\" again.\n<ul>") . join("\n", $va_error_list) . "</ul>", __NOTIFICATION_TYPE_ERROR__);
         } else {
             $this->notification->addNotification($vs_message, __NOTIFICATION_TYPE_INFO__);
             $this->notification->addNotification(_t("There are errors preventing information in specific fields from being saved as noted below.\n<ul>") . join("\n", $va_error_list) . "</ul>", __NOTIFICATION_TYPE_ERROR__);
         }
     } else {
         $this->notification->addNotification($vs_message, __NOTIFICATION_TYPE_INFO__);
         $this->opo_result_context->invalidateCache();
         // force new search in case changes have removed this item from the results
         $this->opo_result_context->saveContext();
     }
     # trigger "SaveItem" hook
     $this->opo_app_plugin_manager->hookSaveItem(array('id' => $vn_subject_id, 'table_num' => $t_subject->tableNum(), 'table_name' => $t_subject->tableName(), 'instance' => $t_subject, 'is_insert' => $vb_is_insert));
     if (method_exists($this, "postSave")) {
         $this->postSave($t_subject, $vb_is_insert);
     }
     // redirect back to previous item on stack if it's a valid "save and return" request
     $vb_has_errors = is_array($va_errors) && sizeof($va_errors) > 0;
     // don't redirect back when there were form errors
     if ((bool) $this->getRequest()->getParameter('is_save_and_return', pInteger) && !$vb_has_errors) {
         $va_save_and_return = $this->getRequest()->session->getVar('save_and_return_locations');
         if (is_array($va_save_and_return)) {
             // get rid of all the navigational steps in the current item
             do {
                 $va_pop = array_pop($va_save_and_return);
             } while (sizeof($va_save_and_return) > 0 && (!$va_pop['key'] || $va_pop['table'] == $t_subject->tableName() && $va_pop['key'] == $vn_subject_id));
             // the last pop must be from a different table or record for the redirect to kick in
             // (which might not be the case because $va_save_and_return might have just run out of items for some reason)
             if ($va_pop['table'] != $t_subject->tableName() || $va_pop['key'] != $vn_subject_id) {
                 if (isset($va_pop['url_path']) && strlen($va_pop['url_path']) > 0) {
                     $this->getResponse()->setRedirect($va_pop['url_path']);
                 } else {
                     $this->getResponse()->setRedirect(caEditorUrl($this->getRequest(), $va_pop['table'], $va_pop['key']));
                 }
             }
         }
     }
     // save where we are in session for "Save and return" button
     if ($vn_subject_id) {
         $va_save_and_return = $this->getRequest()->session->getVar('save_and_return_locations');
         if (!is_array($va_save_and_return)) {
             $va_save_and_return = array();
         }
         $va_save = array('table' => $t_subject->tableName(), 'key' => $vn_subject_id, 'url_path' => str_replace('/Save/', '/Edit/', $this->getRequest()->getFullUrlPath()) . $vn_subject_id);
         $this->getRequest()->session->setVar('save_and_return_locations', caPushToStack($va_save, $va_save_and_return, __CA_SAVE_AND_RETURN_STACK_SIZE__));
     }
     // if we came here through a rel link, show save and return button
     $this->getView()->setVar('show_save_and_return', (bool) $this->getRequest()->getParameter('rel', pInteger));
     $this->render('screen_html.php');
 }
コード例 #11
0
 /**
  * Do search
  *
  * @param int $pn_subject_tablenum
  * @param string $ps_search_expression
  * @param array $pa_filters
  * @param null|Zend_Search_Lucene_Search_Query_Boolean $po_rewritten_query
  * @return WLPlugSearchEngineElasticSearchResult
  */
 public function search($pn_subject_tablenum, $ps_search_expression, $pa_filters = array(), $po_rewritten_query = null)
 {
     Debug::msg("[ElasticSearch] incoming search query is: {$ps_search_expression}");
     Debug::msg("[ElasticSearch] incoming query filters are: " . print_r($pa_filters, true));
     $o_query = new ElasticSearch\Query($pn_subject_tablenum, $ps_search_expression, $po_rewritten_query, $pa_filters);
     $vs_query = $o_query->getSearchExpression();
     Debug::msg("[ElasticSearch] actual search query sent to ES: {$vs_query}");
     $va_search_params = array('index' => $this->getIndexName(), 'type' => $this->opo_datamodel->getTableName($pn_subject_tablenum), 'body' => array('from' => 0, 'size' => 2147483647, 'query' => array('bool' => array('must' => array('query_string' => array('query' => $vs_query))))));
     // apply additional filters that may have been set by the query
     if (($va_additional_filters = $o_query->getAdditionalFilters()) && is_array($va_additional_filters) && sizeof($va_additional_filters) > 0) {
         foreach ($va_additional_filters as $vs_filter_name => $va_filter) {
             $va_search_params['body']['query']['bool']['filter'][$vs_filter_name] = $va_filter;
         }
     }
     Debug::msg("[ElasticSearch] actual query filters are: " . print_r($va_additional_filters, true));
     $va_results = $this->getClient()->search($va_search_params);
     return new WLPlugSearchEngineElasticSearchResult($va_results['hits']['hits'], $pn_subject_tablenum);
 }