|
dmBridge PHP API
|
00001 <?php 00002 # 00003 # dmBridge: a data access framework for CONTENTdm(R) 00004 # 00005 # Copyright © 2009, 2010, 2011 Board of Regents of the Nevada System of Higher 00006 # Education, on behalf of the University of Nevada, Las Vegas 00007 # 00008 00017 class DMInput { 00018 00019 private static $valid_date_qualifiers = array("from", "after", "before", 00020 "on"); 00021 00023 private $begin_date; 00025 private $collections = array(); 00027 private $date_qualifier; 00029 private $end_date; 00031 private $input_terms = array(); 00033 private $is_present = false; 00035 private $on_date; 00037 private $proximity; 00039 private $uri; 00040 00041 00045 public function __construct(DMURI $uri) { 00046 $this->uri = $uri; 00047 $this->assembleUserInput(); 00048 } 00049 00050 private function assembleUserInput() { 00051 $qt = array(); 00052 // simple search input (&q=...) 00053 if ($this->uri->getQueryValue("q")) { 00054 $qt[0]['string'] = $this->uri->getQueryValue("q"); 00055 $qt[0]['field'] = "any"; 00056 $qt[0]['mode'] = "all"; 00057 $this->collections = DMCollection::getAuthorized(); 00058 if (count($this->collections) < 1) { 00059 $this->collections[] = DMCollectionFactory::getCollection("/dmdefault"); 00060 } 00061 } else { // CONTENTdm search (&CISOBLAH=...) 00062 for ($i = 1; $i < 5; $i++) { 00063 if ($this->uri->getQueryValue("CISOBOX" . $i)) { 00064 $qt[$i]['string'] = $this->uri->getQueryValue("CISOBOX" . $i); 00065 } else { 00066 break; 00067 } 00068 00069 if ($this->uri->getQueryValue("CISOFIELD" . $i)) { 00070 $qt[$i]['field'] = $this->uri->getQueryValue("CISOFIELD" . $i); 00071 } else { 00072 break; 00073 } 00074 00075 if ($this->uri->getQueryValue("CISOOP" . $i)) { 00076 $qt[$i]['mode'] = $this->uri->getQueryValue("CISOOP" . $i); 00077 } else { 00078 break; 00079 } 00080 } // for 00081 if ($this->uri->getQueryValue("CISOROOT")) { 00082 // CISOROOT may be a comma-delimited string, or an array. 00083 $aliases = array(); 00084 if (is_array($this->uri->getQueryValue("CISOROOT"))) { 00085 $aliases = $this->uri->getQueryValue("CISOROOT"); 00086 } else { 00087 $aliases = explode(",", 00088 $this->uri->getQueryValue("CISOROOT")); 00089 } 00090 if (in_array("all", $aliases)) { 00091 $this->collections[] = DMCollectionFactory::getCollection("/dmdefault"); 00092 } else { 00093 foreach ($aliases as $a) { 00094 if ($a) { 00095 $this->collections[] = DMCollectionFactory::getCollection($a); 00096 } 00097 } 00098 } 00099 } // if 00100 } // else 00101 00102 // check for presence of CISOROOT, CISOFIELD, CISOOP, or CISOBOX 00103 foreach ($this->uri->getQuery() as $kv) { 00104 if (substr($kv['key'], 0, 8) == "CISOROOT" 00105 || substr($kv['key'], 0, 9) == "CISOFIELD" 00106 || substr($kv['key'], 0, 6) == "CISOOP" 00107 || substr($kv['key'], 0, 7) == "CISOBOX") { 00108 $this->is_present = true; 00109 break; 00110 } 00111 } 00112 00113 foreach ($qt as $t) { 00114 if (!array_key_exists("field", $t)) { 00115 continue; 00116 } 00117 if (!array_key_exists("mode", $t)) { 00118 continue; 00119 } 00120 $f = new DMDCElement($t['field']); 00121 $f->setCollection(DMCollectionFactory::getCollection("/dmdefault")); 00122 $term = new DMQueryPredicate(); 00123 $term->setString($t['string']); 00124 $term->setField(new DMDCElement($f->getNick())); 00125 $term->setMode($t['mode']); 00126 if ($term->isValid()) { 00127 $this->input_terms[] = $term; 00128 } 00129 } 00130 00131 // date stuff 00132 if ($this->uri->getQueryValue("date_qualifier")) { 00133 $this->setDateQualifier( 00134 substr($this->uri->getQueryValue("date_qualifier"), 0, 6)); 00135 } 00136 if ($this->uri->getQueryValue("proximity")) { 00137 $this->setProximity( 00138 (int) substr($this->uri->getQueryValue("proximity"), 0, 3)); 00139 } 00140 00141 if (in_array($this->getDateQualifier(), array("from", "after"))) { 00142 if (strlen($this->uri->getQueryValue("y1")) > 0 00143 && strlen($this->uri->getQueryValue("y1")) <= 8) { 00144 $this->setBeginDate( 00145 new DMDateTime(sprintf("%d-%d-%d", 00146 $this->uri->getQueryValue("y1"), 00147 $this->uri->getQueryValue("m1"), 00148 $this->uri->getQueryValue("d1")))); 00149 } 00150 } 00151 if (in_array($this->getDateQualifier(), array("from", "before"))) { 00152 if (strlen($this->uri->getQueryValue("y2")) > 0 00153 && strlen($this->uri->getQueryValue("y2")) <= 8) { 00154 $this->setEndDate( 00155 new DMDateTime(sprintf('%d-%d-%d', 00156 $this->uri->getQueryValue("y2"), 00157 $this->uri->getQueryValue("m2"), 00158 $this->uri->getQueryValue("d2")))); 00159 } 00160 } 00161 if ($this->getDateQualifier() == "on") { 00162 if (strlen($this->uri->getQueryValue("y1")) > 0 00163 && strlen($this->uri->getQueryValue("y1")) <= 8) { 00164 $this->setOnDate( 00165 new DMDateTime(sprintf('%d-%d-%d', 00166 $this->uri->getQueryValue("y1"), 00167 $this->uri->getQueryValue("m1"), 00168 $this->uri->getQueryValue("d1")))); 00169 } 00170 } 00171 } 00172 00176 public function isPresent() { 00177 return $this->is_present; 00178 } 00179 00184 public function getBeginDate() { 00185 return $this->begin_date; 00186 } 00187 00188 private function setBeginDate(DMDateTime $date) { 00189 $this->begin_date = $date; 00190 } 00191 00196 public function getCollections() { 00197 return $this->collections; 00198 } 00199 00204 public function getDateQualifier() { 00205 return $this->date_qualifier; 00206 } 00207 00208 private function setDateQualifier($q) { 00209 $valid = self::$valid_date_qualifiers; 00210 $valid[] = null; 00211 if (!in_array($q, $valid)) { 00212 throw new DMIllegalArgumentException( 00213 sprintf(DMLocalizedString::getString("INVALID_DATE_QUALIFIER"), 00214 implode(", ", self::$valid_date_qualifiers))); 00215 } 00216 $this->date_qualifier = $q; 00217 } 00218 00223 public function getEndDate() { 00224 return $this->end_date; 00225 } 00226 00227 private function setEndDate(DMDateTime $date) { 00228 $this->end_date = $date; 00229 } 00230 00235 public function getOnDate() { 00236 return $this->on_date; 00237 } 00238 00239 private function setOnDate(DMDateTime $date) { 00240 $this->on_date = $date; 00241 } 00242 00246 public function getProximity() { 00247 return $this->proximity; 00248 } 00249 00250 private function setProximity($int) { 00251 $this->proximity = $int; 00252 } 00253 00259 public function getPredicate($index) { 00260 $terms = $this->getTerms(); 00261 if ($index + 1 > count($terms)) { 00262 return false; 00263 } 00264 return ($terms[$index] instanceof DMQueryPredicate) 00265 ? $terms[$index] : null; 00266 } 00267 00272 public function getTerms() { 00273 $begin_date = "00000000"; 00274 if ($this->getBeginDate() instanceof DMDateTime) { 00275 $begin_date = $this->getBeginDate()->format("Ymd"); 00276 } 00277 00278 $end_date = "99999999"; 00279 if ($this->getEndDate() instanceof DMDateTime) { 00280 $end_date = $this->getEndDate()->format("Ymd"); 00281 } 00282 00283 $terms = array(); 00284 foreach ($this->input_terms as $t) { 00285 $terms[] = clone($t); 00286 } 00287 00288 if (count($terms) < 1) { 00289 return array(); 00290 } 00291 00292 $on_date = null; 00293 if ($this->getOnDate() instanceof DMDateTime) { 00294 $on_date = $this->getOnDate()->format("Ymd"); 00295 } 00296 00297 // date search 00298 if (!($begin_date == "00000000" && $end_date == "99999999" 00299 && empty($on_date))) { 00300 if (!$this->collections[0] instanceof DMCollection) { 00301 return array(); 00302 } 00303 $nick = $this->collections[0]->getDateSearchField()->getNick(); 00304 $m = "exact"; 00305 $s = ($on_date) ? $on_date : $begin_date . "-" . $end_date; 00306 if ($terms[1] instanceof DMQueryPredicate) { 00307 $terms[1]->setDate(true); 00308 $terms[1]->setString($s); 00309 $terms[1]->setField(new DMDCElement($nick)); 00310 $terms[1]->setMode($m); 00311 } else { 00312 $term = new DMQueryPredicate(); 00313 $term->setString($s); 00314 $term->setField(new DMDCElement($nick)); 00315 $term->setMode($m); 00316 $term->setDate(true); 00317 $terms[] = $term; 00318 } 00319 } else if ($this->getProximity() > 0) { // proximity search 00320 $s = sprintf("%s near%d %s", 00321 $terms[0]->getString(), 00322 $this->getProximity(), 00323 $terms[1]->getString() 00324 ); 00325 $m = "exact"; 00326 $term = new DMQueryPredicate(); 00327 $term->setString($s); 00328 $term->setField(new DMDCElement("any")); 00329 $term->setMode($m); 00330 $term->setProximity(true); 00331 $terms = array($term); 00332 } 00333 00334 return $terms; 00335 } 00336 00342 public function validate() { 00343 // if no date is set, make sure all fields have been filled in 00344 if (!$this->getBeginDate() instanceof DMDateTime 00345 && !$this->getEndDate() instanceof DMDateTime 00346 && !$this->getOnDate() instanceof DMDateTime) { 00347 $i = 0; 00348 foreach ($this->getTerms() as $t) { 00349 if (strlen($t->getString()) < 1) { 00350 $i++; 00351 } 00352 } 00353 if ($i == count($this->getTerms())) { 00354 throw new DMIllegalArgumentException( 00355 DMLocalizedString::getString("MISSING_SEARCH_TERM")); 00356 } 00357 } 00358 // make sure end date is always >= begin date 00359 if ($this->getBeginDate() instanceof DMDateTime 00360 && $this->getEndDate() instanceof DMDateTime) { 00361 if ($this->getBeginDate() > $this->getEndDate()) { 00362 throw new DMIllegalArgumentException( 00363 DMLocalizedString::getString("FROM_DATE_LATER")); 00364 } 00365 } 00366 // if a date is chosen... 00367 if ($this->getBeginDate() instanceof DMDateTime 00368 || $this->getEndDate() instanceof DMDateTime) { 00369 // make sure there is only one term 00370 // (count is 2 because the date is always the 2nd term) 00371 if (count($this->getTerms()) > 2) { 00372 throw new DMIllegalArgumentException( 00373 DMLocalizedString::getString("MAX_TERMS_IN_DATE_SEARCH")); 00374 } 00375 // make sure a specific field is being searched (not "any") 00376 foreach ($this->getTerms() as $t) { 00377 if ($t->getField()->getNick() == "any") { 00378 throw new DMIllegalArgumentException( 00379 DMLocalizedString::getString("ANY_FIELD_IN_DATE_SEARCH")); 00380 } 00381 } 00382 } 00383 // if 'none' is selected as a mode, make sure another mode has been 00384 // selected as well (cdm doesn't like the "naked none") 00385 $tmp = array(); 00386 foreach ($this->getTerms() as $t) { 00387 $tmp[] = $t->getMode(); 00388 } 00389 $tmp = array_unique($tmp); 00390 if (in_array("none", $tmp) && count($tmp) == 1) { 00391 throw new DMIllegalArgumentException( 00392 DMLocalizedString::getString("NAKED_NONE_OPERAND")); 00393 } 00394 // if a proximity int is supplied, make sure both strings exist 00395 if ($this->getProximity() > 0) { 00396 $i = 0; 00397 foreach ($this->input_terms as $t) { 00398 if (strlen($t->getString()) > 0) { 00399 $i++; 00400 } 00401 } 00402 if ($i < 2) { 00403 throw new DMIllegalArgumentException( 00404 DMLocalizedString::getString("MISSING_PROXIMITY_STRING")); 00405 } 00406 } 00407 00408 return true; 00409 } 00410 00411 }