/** * 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; }
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; }
/** * 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); } }
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); }
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); }
/** * 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('/', '/', $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('/', '/', $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; }
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); }
/** * * * @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"); } } }
/** * 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; }
/** * 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'); }
/** * 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); }