public function parseValue($ps_value, $pa_element_info, $pa_options = null) { $o_date_config = Configuration::load(__CA_CONF_DIR__ . '/datetime.conf'); $show_Undated = $o_date_config->get('showUndated'); $ps_value = trim($ps_value); $va_settings = $this->getSettingValuesFromElementArray($pa_element_info, array('dateRangeBoundaries', 'mustNotBeBlank')); if ($ps_value) { if (!DateRangeAttributeValue::$o_tep->parse($ps_value)) { // invalid date $this->postError(1970, _t('%1 is invalid', $pa_element_info['displayLabel']), 'DateRangeAttributeValue->parseValue()'); return false; } $va_dates = DateRangeAttributeValue::$o_tep->getHistoricTimestamps(); if ($va_settings['dateRangeBoundaries']) { if (DateRangeAttributeValue::$o_tep->parse($va_settings['dateRangeBoundaries'])) { $va_boundary_dates = DateRangeAttributeValue::$o_tep->getHistoricTimestamps(); if ($va_dates[0] < $va_boundary_dates[0] || $va_dates[0] > $va_boundary_dates[1] || $va_dates[1] < $va_boundary_dates[0] || $va_dates[1] > $va_boundary_dates[1]) { // date is out of bounds $this->postError(1970, _t('%1 must be within %2', $pa_element_info['displayLabel'], $va_settings['dateRangeBoundaries']), 'DateRangeAttributeValue->parseValue()'); return false; } } } } else { if ((bool) $va_settings['mustNotBeBlank']) { $this->postError(1970, _t('%1 must not be empty', $pa_element_info['displayLabel']), 'DateRangeAttributeValue->parseValue()'); return false; } else { $o_date_config = Configuration::load(__CA_CONF_DIR__ . '/datetime.conf'); // Default to "undated" date for blanks $vs_undated_date = ''; if ((bool) $o_date_config->get('showUndated')) { $o_lang_config = DateRangeAttributeValue::$o_tep->getLanguageSettings(); $vs_undated_date = array_shift($o_lang_config->getList('undatedDate')); } return array('value_longtext1' => $vs_undated_date, 'value_decimal1' => null, 'value_decimal2' => null); } } return array('value_longtext1' => $ps_value, 'value_decimal1' => $va_dates[0], 'value_decimal2' => $va_dates[1]); }
/** * Returns version of label 'display' field value suitable for sorting * The sortable value is the same as the display value except when the display value * starts with a definite article ('the' in English) or indefinite article ('a' or 'an' in English) * in the locale of the label, in which case the article is moved to the end of the sortable value. * * What constitutes an article is defined in the TimeExpressionParser localization files. So if the * locale of the label doesn't correspond to an existing TimeExpressionParser localization, then * the users' current locale setting is used. */ private function _generateSortableValue() { if ($vs_sort_field = $this->getProperty('LABEL_SORT_FIELD')) { $vs_display_field = $this->getProperty('LABEL_DISPLAY_FIELD'); $o_tep = new TimeExpressionParser(); $t_locale = new ca_locales(); $o_tep->setLanguage($t_locale->localeIDToCode($this->get('locale_id'))); $o_lang_settings = $o_tep->getLanguageSettings(); $vs_display_value = trim(preg_replace('![^\\p{L}0-9 ]+!u', ' ', $this->get($vs_display_field))); $va_definite_articles = $o_lang_settings->get('definiteArticles'); $va_indefinite_articles = $o_lang_settings->get('indefiniteArticles'); foreach (array($o_lang_settings->get('definiteArticles'), $o_lang_settings->get('indefiniteArticles')) as $va_articles) { if (is_array($va_articles)) { foreach ($va_articles as $vs_article) { if (preg_match('!^(' . $vs_article . ')[ ]+!i', $vs_display_value, $va_matches)) { $vs_display_value = trim(str_replace($va_matches[1], '', $vs_display_value) . ', ' . $va_matches[1]); break 2; } } } } $this->set($vs_sort_field, $vs_display_value); } }
public function parseValue($ps_value, $pa_element_info, $pa_options = null) { $ps_value = trim($ps_value); $va_settings = $this->getSettingValuesFromElementArray($pa_element_info, array('dateRangeBoundaries', 'mustNotBeBlank')); $o_tep = new TimeExpressionParser(); if ($ps_value) { if (!$o_tep->parse($ps_value)) { // invalid date $this->postError(1970, _t('%1 is invalid', $pa_element_info['displayLabel']), 'DateRangeAttributeValue->parseValue()'); return false; } $va_dates = $o_tep->getHistoricTimestamps(); if ($va_settings['dateRangeBoundaries']) { if ($o_tep->parse($va_settings['dateRangeBoundaries'])) { $va_boundary_dates = $o_tep->getHistoricTimestamps(); if ($va_dates[0] < $va_boundary_dates[0] || $va_dates[0] > $va_boundary_dates[1] || $va_dates[1] < $va_boundary_dates[0] || $va_dates[1] > $va_boundary_dates[1]) { // date is out of bounds $this->postError(1970, _t('%1 must be within %2', $pa_element_info['displayLabel'], $va_settings['dateRangeBoundaries']), 'DateRangeAttributeValue->parseValue()'); return false; } } } } else { if ((bool) $va_settings['mustNotBeBlank']) { $this->postError(1970, _t('%1 must not be empty', $pa_element_info['displayLabel']), 'DateRangeAttributeValue->parseValue()'); return false; } else { // Default to "undated" date for blanks $o_config = $o_tep->getLanguageSettings(); $va_undated_dates = $o_config->getList('undatedDate'); return array('value_longtext1' => $va_undated_dates[0], 'value_decimal1' => null, 'value_decimal2' => null); } } return array('value_longtext1' => $ps_value, 'value_decimal1' => $va_dates[0], 'value_decimal2' => $va_dates[1]); }
/** * Responds to the two main List verbs, includes resumption and limiting. * * @param string $verb OAI-PMH verb for the request * @param string $metadataPrefix Metadata prefix * @param int $cursor Offset in response to begin output at * @param mixed $set Optional set argument * @param string $from Optional from date argument * @param string $until Optional until date argument * @uses createResumptionToken() */ private function listResponse($oaiData, $verb, $metadataPrefix, $cursor, $set, $from, $until) { $listLimit = $this->_listLimit; $o_dm = Datamodel::load(); // by this point, the mapping code was checked to be valid $t_instance = $o_dm->getInstanceByTableName($this->table, true); $vs_pk = $t_instance->primaryKey(); $va_access_values = caGetUserAccessValues($this->opo_request, $this->opa_provider_info); $vb_show_deleted = (bool) $this->opa_provider_info['show_deleted']; $vb_dont_enforce_access_settings = (bool) $this->opa_provider_info['dont_enforce_access_settings']; $vb_dont_cache = (bool) $this->opa_provider_info['dont_cache']; $vs_table = $t_instance->tableName(); if (!($o_search = caGetSearchInstance($vs_table))) { $this->throwError(self::OAI_ERR_BAD_ARGUMENT); return; } // Construct date range for from/until if defined $o_tep = new TimeExpressionParser(); $o_lang_settings = $o_tep->getLanguageSettings(); $vs_conj = array_shift($o_lang_settings->getList("rangeConjunctions")); $vs_range = $from && $until ? "{$from} {$vs_conj} {$until}" : ''; if ($set && $this->opa_provider_info['setFacet']) { $o_browse = caGetBrowseInstance($this->table); if (($vs_query = $this->opa_provider_info['query']) && $vs_query != "*") { $o_browse->addCriteria("_search", $vs_query); } $o_browse->addCriteria($this->opa_provider_info['setFacet'], $set); $o_browse->execute(array('showDeleted' => $vb_show_deleted, 'no_cache' => $vb_dont_cache, 'limitToModifiedOn' => $vs_range, 'checkAccess' => $vb_dont_enforce_access_settings ? null : $va_access_values)); $qr_res = $o_browse->getResults(); } else { $qr_res = $o_search->search(strlen($this->opa_provider_info['query']) ? $this->opa_provider_info['query'] : "*", array('no_cache' => $vb_dont_cache, 'limitToModifiedOn' => $vs_range, 'showDeleted' => $vb_show_deleted, 'checkAccess' => $vb_dont_enforce_access_settings ? null : $va_access_values)); } if (!$qr_res) { $this->throwError(self::OAI_ERR_NO_RECORDS_MATCH, _t('Query failed')); return; } $rows = $qr_res->numHits(); if (count($qr_res->numHits()) == 0) { $this->throwError(self::OAI_ERR_NO_RECORDS_MATCH, _t('No records match the given criteria')); } else { $verbElement = $oaiData->createElement($verb); $oaiData->documentElement->appendChild($verbElement); $t_change_log = new ApplicationChangeLog(); if ($vb_show_deleted) { // get list of deleted records $va_deleted_items = array(); $qr_res->seek($cursor); $vn_c = 0; $va_get_deleted_timestamps_for = array(); while ($qr_res->nextHit()) { if ((bool) $qr_res->get("{$vs_table}.deleted")) { $va_deleted_items[$vs_pk_val = (int) $qr_res->get("{$vs_table}.{$vs_pk}")] = true; $va_get_deleted_timestamps_for[$vs_pk_val] = true; } else { $vn_access = (int) $qr_res->get("{$vs_table}.access"); if (!in_array($vn_access, $va_access_values)) { $va_deleted_items[(int) $qr_res->get("{$vs_table}.{$vs_pk}")] = true; } } $vn_c++; if ($vn_c >= $listLimit) { break; } } $qr_res->seek(0); $va_deleted_timestamps = $t_change_log->getDeleteOnTimestampsForIDs($vs_table, array_keys($va_get_deleted_timestamps_for)); } // Export data using metadata mapping $va_items = ca_data_exporters::exportRecordsFromSearchResultToArray($this->getMappingCode(), $qr_res, array('start' => $cursor, 'limit' => $listLimit)); if (is_array($va_items) && sizeof($va_items)) { $va_timestamps = $t_change_log->getLastChangeTimestampsForIDs($vs_table, array_keys($va_items)); foreach ($va_items as $vn_id => $vs_item_xml) { if ($vb_show_deleted && $va_deleted_items[$vn_id]) { $headerData = array('identifier' => OaiIdentifier::itemToOaiId($vn_id), 'datestamp' => self::unixToUtc($va_deleted_timestamps[$vn_id]['timestamp'] ? $va_deleted_timestamps[$vn_id]['timestamp'] : $va_timestamps[$vn_id]['timestamp'])); if ($verb == 'ListIdentifiers') { $header = $this->createElementWithChildren($oaiData, $verbElement, 'header', $headerData); $header->setAttribute("status", "deleted"); } else { $recordElement = $verbElement->appendChild($oaiData->createElement('record')); $header = $this->createElementWithChildren($oaiData, $recordElement, 'header', $headerData); $header->setAttribute("status", "deleted"); } } else { $headerData = array('identifier' => OaiIdentifier::itemToOaiId($vn_id), 'datestamp' => self::unixToUtc($va_timestamps[$vn_id]['timestamp'])); if ($verb == 'ListIdentifiers') { $this->createElementWithChildren($oaiData, $verbElement, 'header', $headerData); } else { $recordElement = $verbElement->appendChild($oaiData->createElement('record')); $this->createElementWithChildren($oaiData, $recordElement, 'header', $headerData); $metadataElement = $oaiData->createElement('metadata'); $o_doc_src = DomDocument::loadXML($vs_item_xml); if ($o_doc_src) { // just in case the xml fails to load through DomDocument for some reason (e.g. a bad mapping or very weird characters) $metadataElement->appendChild($oaiData->importNode($o_doc_src->documentElement, true)); } $recordElement->appendChild($metadataElement); } } } } if ($rows > $cursor + $listLimit) { $token = $this->createResumptionToken($verb, $metadataPrefix, $cursor + $listLimit, $set, $from, $until); $tokenElement = $oaiData->createElement('resumptionToken', $token['key']); $tokenElement->setAttribute('expirationDate', self::unixToUtc($token['expiration'])); $tokenElement->setAttribute('completeListSize', $rows); $tokenElement->setAttribute('cursor', $cursor); $verbElement->appendChild($tokenElement); } else { if ($cursor != 0) { $tokenElement = $this->oaiData->createElement('resumptionToken'); $verbElement->appendChild($tokenElement); } } } }