00001 <?php
00002
00006 abstract class SDRService extends SObject {
00007 private static $isInit = false;
00008 public static $DBI_NAME = 'SDR2';
00009 const FORM_ERROR = -1;
00010 const FORM_INPROCESS = -2;
00011
00015 public function init() {
00016 if (self::$isInit)
00017 return true;
00018 $DBI = DBI2::getDBI(self::$DBI_NAME);
00019 if ($DBI == null) {
00020 $DBI = new DBI2(self::$DBI_NAME,
00021 SConfig::getOption('sdr.db_host'),
00022 SConfig::getOption('sdr.db_name'),
00023 SConfig::getOption('sdr.db_user'),
00024 SConfig::getOption('sdr.db_pass'));
00025 $DBI->setDefaultOperator('= BINARY');
00026 }
00027 self::$isInit = true;
00028 return true;
00029 }
00030
00060 public static function submit($cserdId, $metadata, $agent, $comment, $projectName = null) {
00061
00062 if ($cserdId == '') {
00063 self::setStaticError('No CSERD ID specified.');
00064 return false;
00065 }
00066 if (!($metadata instanceOf SDRMetadataObj)) {
00067 self::setStaticError('Metadata must be SDRMetadataObj');
00068 return false;
00069 }
00070 if (!($agent instanceOf SDRAgent)) {
00071 self::setStaticError('Agent must be SDRAgent');
00072 return false;
00073 }
00074 if (!is_string($comment) && ($comment != '')) {
00075 self::setStaticError('Comment must be a string');
00076 return false;
00077 }
00078
00079
00080
00081 $resource = self::resolveResource($cserdId, $metadata->Url[0], $projectName);
00082 if (!$resource) {
00083 self::setStaticError('Could not resolve resource for cserdId ' . $cserdId);
00084 return false;
00085 }
00086
00087
00088 $version = SDRVersion::createVersion($resource->cserdId, $agent->id, $agent->id, $comment);
00089 if ($version === false) {
00090 self::setStaticError('Error creating a new version to store submission.');
00091 return false;
00092 }
00093
00094
00095
00096 foreach ($metadata->getAttributes() as $attr) {
00097
00098 $field = SDRField::findOrAddField($attr);
00099 if (!$field) {
00100 self::setStaticError('Could not find or add field for metadata '
00101 . 'attribute ' . $attr . '.');
00102 return false;
00103 }
00104
00105 if ($projectName != null) {
00106 $projectList = SDRProject::getList(array('name'=>$projectName));
00107 foreach ($projectList as $project)
00108 SDRProjectField::findOrAddProjectField($field->id, $project->id);
00109 }
00110
00111
00112
00113 $values = $metadata->$attr;
00114 if (!is_array($values))
00115 $values = array($values);
00116
00117 foreach($values as $entry) {
00118 $entry = trim($entry);
00119 if($entry == '')
00120 continue;
00121 $value = SDRValue::findOrAddValue($entry, $field);
00122 if (!$value){
00123 self::setStaticError('Could not find or add value ' . $entry);
00124 return false;
00125 }
00126
00127
00128 $vfv = new SDRVersionFieldValue();
00129 $vfv->versionId = $version->id;
00130 $vfv->fieldId = $field->id;
00131 $vfv->valueId = $value->id;
00132 if (!$vfv->commit()) {
00133 self::setStaticError('Could not commit link value '
00134 . $value->id . ' to version ' . $version->id);
00135 return false;
00136 }
00137
00138
00139 }
00140 }
00141
00142 SDRServiceCache::updateValueCache();
00143 SDRServiceCache::updateResourceCacheHelper($resource);
00144
00145 return $version;
00146 }
00147
00148
00149
00150
00151
00160 private static function resolveProjects($projects = null) {
00161
00162 if ($projects == null)
00163 return array(self::getCSERDProject());
00164
00165 if (!is_array($projects))
00166 $projects = array($projects);
00167
00168 $resolvedProjects = array();
00169 $rpc = 0;
00170 foreach($projects as $project) {
00171
00172 if (($project instanceOf SDRProject) && ($project->id != ''))
00173 $resolvedProjects[$rpc] = $project;
00174
00175 else if (is_string($project) && ($project != '') && ($project != null)) {
00176 $projects = SDRProject::getList(array('name' => $project));
00177 if (count($projects) == 0) {
00178 self::setStaticError('Requested project ' . $project . ' not found');
00179 return false;
00180 }
00181 $resolvedProjects[$rpc] = $projects[0];
00182
00183 } else {
00184 self::setStaticError('Unknown project requested: ' . $project);
00185 return false;
00186 }
00187 $rpc++;
00188 }
00189 return $resolvedProjects;
00190 }
00191
00192
00193
00194
00195
00203 private static function getCSERDProject() {
00204 $projects = SDRProject::getList(array('name' => 'CSERD'));
00205 if (count($projects) == 0) {
00206 self::setStaticError('CSERD project not found');
00207 return false;
00208 }
00209 return $projects[0];
00210 }
00211
00212
00213
00214
00215
00216
00217
00218
00219
00220
00221
00222
00223
00224
00225
00236 private static function resolveResource($cserdId, $url, $projects) {
00237
00238 $rid = self::identifierToCserdId($cserdId);
00239 if ($rid === false)
00240 return false;
00241 if ($rid === null) {
00242
00243 $projects = self::resolveProjects($projects);
00244 if (!$projects)
00245 return false;
00246 $res = self::newResource($cserdId, $url, $projects);
00247 if ($res === false)
00248 return false;
00249 } else {
00250
00251 $res = new SDRResource(array('cserdId' => $rid));
00252 if (!$res) {
00253 self::setStaticError('Unable to populate resource from CSERD Id ' . $rid);
00254 return false;
00255 }
00256 }
00257 return $res;
00258 }
00259
00260
00261
00262
00263
00264
00265
00266
00277 private static function newResource($cserdId, $url, $projects) {
00278
00279 if (!$url) {
00280 self::setStaticError('URL required when creating a new resource.');
00281 return false;
00282 }
00283 if (!is_array($projects) || count($projects) == 0 || !isset($projects[0])) {
00284 self::setStaticError('No projects specified. New resources require at least one.');
00285 return false;
00286 }
00287
00288
00289
00290 if (self::URLExists($url)) {
00291 self::setStaticError('URL ' . $url . ' conflicts with an existing catalog URL.');
00292 return false;
00293 }
00294 $res = new SDRResource();
00295
00296 if (ctype_digit((string) $cserdId))
00297 $res->cserdId = $cserdId;
00298
00299 else
00300 $res->cserdId = self::nextCserdId();
00301 $res->url = $url;
00302 $res->releaseFlag = false;
00303 $res->primaryProject = $projects[0]->id;
00304 if (!$res->commit()) {
00305 self::setStaticError('Unable to commit resource ' . $res->cserdId);
00306 return false;
00307 }
00308
00309 $addedProjects = array();
00310 for ($i = 0; $i < count($projects); $i++) {
00311
00312 if (in_array($projects[$i]->id, $addedProjects))
00313 continue;
00314
00315 if (!self::addProjectToResource($projects[$i], $res->cserdId))
00316 return false;
00317 $addedProjects []= $projects[$i]->id;
00318 }
00319 return $res;
00320 }
00321
00322
00323
00324
00325
00326
00327
00337 private function addProjectToResource($project, $cserdId) {
00338
00339 $link = new SDRResourceProject();
00340 $link->cserdId = $cserdId;
00341
00342 if ($project instanceOf SDRProject)
00343 $link->projectId = $project->id;
00344
00345 else if (ctype_digit((string) $project))
00346 $link->projectId = $project;
00347
00348 else
00349 self::setStaticError('Project is not an object or an id');
00350 if (!$link->commit()) {
00351 self::setStaticError('Error adding project ' . $link->projectId
00352 . ' to resource ' . $link->cserdId);
00353 return false;
00354 }
00355 return $link;
00356 }
00357
00363 public function getProjectsForResource($cserdId) {
00364 if ($cserdId instanceOf SDRResource)
00365 $cserdId = $cserdId->cserdId;
00366 $rid = self::identifierToCserdId($cserdId);
00367 if ($rid === false || $rid === null)
00368 return false;
00369 $projs = SDRResourceProject::getList(array('cserdId' => $rid));
00370 $projects = array();
00371 foreach($projs as $p) {
00372 $projects []= new SDRProject(array('id' => $p->projectId));
00373 }
00374 return $projects;
00375 }
00376
00384 public function getProjects() {
00385 return SDRProject::getList();
00386 }
00387
00404 public static function approve($version, $agent, $state = SDRVersion::STATE_LIVE) {
00405 if (!$version) {
00406 self::setStaticError('Version provided is null.');
00407 return false;
00408 }
00409
00410 if (!($state == SDRVersion::STATE_DEV || $state == SDRVersion::STATE_LIVE)) {
00411 self::setStaticError('Invalid state: '.$state);
00412 return false;
00413 }
00414
00415
00416 $DBI = self::getDBI();
00417 $DBI->startTransaction();
00418
00419
00420 $sameState = SDRVersion::getList(array('cserdId' => $version->cserdId,
00421 'state' => $state));
00422 foreach($sameState as $vSame) {
00423 $vSame->state = SDRVersion::STATE_HISTORY;
00424 if (!$vSame->commit()) {
00425 self::setStaticError('Error updating the state of ' . $vSame->id . ' to history.');
00426 return false;
00427 }
00428 }
00429
00430
00431 $md = $version->getMetadata();
00432 $newUrl = $md->Url[0];
00433 if (!$newUrl) {
00434 self::setStaticError('Invalid new URL');
00435 return false;
00436 }
00437
00438 $version->state = $state;
00439 $version->modifiedAgentId = $agent->id;
00440 if(!$version->commit()) {
00441 if (isset($vLive) && $vLive != null)
00442 self::setStaticError('Unable to update version ' . $vLive->id . ' to live.');
00443 else
00444 self::setStaticError('Unable to approve first version of resource id '
00445 . $version->cserdId);
00446 return false;
00447 }
00448
00449
00450 $res = new SDRResource(array('cserdId' => $version->cserdId));
00451 $res->url = $newUrl;
00452 if (!$res->commit()) {
00453 self::setStaticError('Could not update resource URL from new metadata version.');
00454 return false;
00455 }
00456
00457 if (!SDRServiceCache::updateResourceVersionCaches($res,$version)) {
00458 self::setStaticWarning('Error updating resource/version/quick search cache.');
00459 }
00460 $DBI->commitTransaction();
00461 return true;
00462 }
00463
00477 public static function reject($version, $agent) {
00478 $version->state = SDRVersion::STATE_REJECTED;
00479 $version->modifiedAgentId = $agent->id;
00480 if(!$version->commit()) {
00481 self::setStaticError('Unable to update version ' . $version->id . ' to rejected.');
00482 return false;
00483 }
00484
00485 $live = self::getVersion($version->cserdId, array(SDRVersion::STATE_LIVE, SDRVersion::STATE_DEV));
00486 if ($live === null) {
00487 self::updateReleaseFlag($version->cserdId, 0, $agent);
00488 }
00489
00490 $res = new SDRResource(array('cserdId' => $version->cserdId));
00491 if (!SDRServiceCache::updateResourceVersionCaches($res,$version)) {
00492 self::setStaticWarning('Error updating resource/version/quick search cache.');
00493 }
00494 return true;
00495 }
00496
00505 public static function updateReleaseFlag($cserdId, $value, $agent) {
00506 $rid = self::identifierToCserdId($cserdId);
00507 if ($rid === false || $rid === null)
00508 return false;
00509 $res = new SDRResource(array('cserdId' => $rid));
00510 if (!$res) {
00511 self::setStaticError('Unable to populate resource from CSERD Id ' . $rid);
00512 return false;
00513 }
00514
00515 if ($value){
00516 $checkApproved = self::getVersion($rid, array(SDRVersion::STATE_LIVE, SDRVersion::STATE_DEV));
00517 if (!$checkApproved) {
00518 self::setStaticError('Cannot release a resource with no approved versions.');
00519 return false;
00520 }
00521 }
00522 $res->releaseFlag = $value;
00523 if(!$res->commit()) {
00524 self::setStaticError('Unable to commit resource');
00525 return false;
00526 }
00527
00528 if (SDRServiceCache::updateResourceCacheHelper($res) === false) {
00529 self::setStaticWarning('Error updating resource cache.');
00530 }
00531 return true;
00532 }
00533
00546 public static function getMetadata($identifier, $versionId = null) {
00547 if ($versionId == null)
00548 $result = self::getVersion($identifier, array(SDRVersion::STATE_LIVE, SDRVersion::STATE_DEV));
00549 else
00550 $result = new SDRVersion(array('id'=>$versionId));
00551 if (!$result)
00552 return $result;
00553 else
00554 return $result->getMetadata();
00555 }
00556
00564 public static function getLastModifiedVersion($identifier) {
00565 $cid = self::identifierToCserdId($identifier);
00566 if ($cid === false)
00567 return false;
00568 if ($cid === null) {
00569
00570 return null;
00571 }
00572
00573 $verList = SDRVersion::getList(array('cserdId' => $cid),
00574 array(1),
00575 array('modified' => 'DESC'));
00576 return $verList[0];
00577
00578 }
00579
00580
00589 public static function getVersion($identifier, $state = SDRVersion::STATE_LIVE) {
00590 $cid = self::identifierToCserdId($identifier);
00591 if ($cid === false)
00592 return false;
00593 if ($cid === null) {
00594
00595 return null;
00596 }
00597 if (!is_array($state))
00598 $state = array($state);
00599
00600
00601 if (array_search(SDRVersion::STATE_LIVE, $state) !== false) {
00602 $verList = SDRVersion::getList(array('cserdId' => $cid, 'state'=>SDRVersion::STATE_LIVE),
00603 array(1),
00604 array('modified' => 'DESC'));
00605
00606 if (count($verList) == 1) {
00607 return $verList[0];
00608 }
00609 } if (array_search(SDRVersion::STATE_DEV, $state) !== false) {
00610 $verList = SDRVersion::getList(array('cserdId' => $cid, 'state'=>SDRVersion::STATE_DEV),
00611 array(1),
00612 array('modified' => 'DESC'));
00613
00614 if (count($verList) == 1) {
00615 return $verList[0];
00616 }
00617 }
00618 return null;
00619 }
00620
00627 public static function getResource($identifier) {
00628 $cid = self::identifierToCserdId($identifier);
00629 if ($cid === false)
00630 return false;
00631 if ($cid === null) {
00632
00633 return null;
00634 }
00635 $res = new SDRResource(array('cserdId' => $cid));
00636 if ($res->hasError()) {
00637 return null;
00638 }
00639 return $res;
00640 }
00641
00650 public static function fieldsForProject($project) {
00651 # code...
00652 }
00653
00662 public static function valuesForField($field) {
00663 # code...
00664 }
00665
00674 public static function versionsForResource($cserdId) {
00675 # code...
00676 }
00677
00678
00682 public static function identifierToURL($cserdId) {
00683 if (ctype_digit((string) $cserdId)) {
00684 return getURLForCserdId($cserdId);
00685 } else {
00686 return (self::URLExists($cserdId)) ? $cserdId : null;
00687 }
00688 }
00689
00695 public static function identifierToCserdId($cserdId) {
00696 if (ctype_digit((string) $cserdId)) {
00697 return (self::cserdIdExists($cserdId)) ? $cserdId : null;
00698 } else {
00699 return self::getCserdIdForURL($cserdId);
00700 }
00701 }
00702
00709 public static function getCserdIdForURL($url) {
00710 $DBI = self::getDBI();
00711 $result = $DBI->select('SDRResource', array('cserdId'), array('url' => $url), array(1));
00712 if (!$result)
00713 return false;
00714 if (!count($result))
00715 return null;
00716 $row = $result->nextRow();
00717 return $row['cserdId'];
00718 }
00719
00726 public static function getURLForCserdId($id) {
00727 $DBI = self::getDBI();
00728 if (!ctype_digit((string) $id)) {
00729 self::setStaticError('Non-numeric resource id provided');
00730 return false;
00731 }
00732 $result = $DBI->select('SDRResource', array('url'), array('cserdId' => $id), array(1));
00733 if (!$result)
00734 return false;
00735 if (!count($result))
00736 return null;
00737 $row = $result->nextRow();
00738 return $row['url'];
00739 }
00740
00747 public static function cserdIdExists($id) {
00748 $DBI = self::getDBI();
00749 if (!ctype_digit((string) $id)) {
00750 self::setStaticError('Non-numeric resource id provided');
00751 return false;
00752 }
00753 $result = $DBI->select('SDRResource', array('cserdId'), array('cserdId' => $id), array(1));
00754 if (!$result) {
00755 self::setStaticError('Could not query SDR to find if id ' . $id . ' exists.');
00756 return null;
00757 }
00758 if (!count($result))
00759 return false;
00760 return true;
00761 }
00762
00769 public static function URLExists($url) {
00770 $DBI = self::getDBI();
00771 $result = $DBI->select('SDRResource', array('url'), array('url' => $url), array(1));
00772 if (!$result)
00773 return null;
00774 if (!count($result))
00775 return false;
00776 return true;
00777 }
00778
00788 public static function findResourcesByIdentifier($identifier, $limit = null) {
00789 if (!is_array($identifier))
00790 $identifier = array($identifier);
00791 $DBI = self::getDBI();
00792 $query = 'SELECT cserdId, url, title FROM view_sdrresourceminimal WHERE ';
00793 $constraints = array();
00794 foreach($identifier as $idval){
00795 $idval = trim($idval);
00796 $constraints []= 'cserdId LIKE "%' . mysql_escape_string($idval) . '%"';
00797 $constraints []= 'url LIKE "%' . mysql_escape_string($idval) . '%"';
00798 $constraints []= 'title LIKE "%' . mysql_escape_string($idval) . '%"';
00799 }
00800 $query .= implode(' OR ', $constraints);
00801 if ($limit)
00802 $query .= ' LIMIT ' . $limit;
00803 $result = $DBI->query($query);
00804 if (!$result) {
00805 self::setStaticError('Error finding resources by identifier ' . $identifier);
00806 return false;
00807 }
00808 $return = array();
00809 foreach ($result as $res) {
00810 $rm = new View_SDRResourceMinimal();
00811 $rm->cserdId = $res['cserdId'];
00812 $rm->url = $res['url'];
00813 if (isset($res['title']))
00814 $rm->title = $res['title'];
00815 $return []= $rm;
00816 }
00817 return $return;
00818 }
00819
00820
00821
00822
00830 private static function nextCserdId() {
00831 $DBI = self::getDBI();
00832 $query = 'SELECT (MAX(cserdId)+1) AS next FROM SDRResource';
00833 $result = $DBI->query($query);
00834 if (!$result) return false;
00835 $value = $result->nextRow();
00836 if ($value['next'] === null)
00837 return 1;
00838 else
00839 return $value['next'];
00840 }
00841
00845 public static function getDBI() {
00846 if (!(self::$isInit))
00847 self::init();
00848 return DBI2::getDBI(self::$DBI_NAME);
00849 }
00850
00851
00862 public static function addMetadataEditor($prm, $projectName='CSERD', $cserdId = null, $versionId = null) {
00863 global $SWAT;
00864
00865
00867
00868 $xform = new XFormsRenderModule();
00869
00870 $formXML = self::buildMetadataForm($cserdId, $projectName, $versionId);
00871 $xform->loadXML($formXML);
00872
00873 # Process any input already sent by the user
00874 $xform->processInput();
00875
00876 if ($xform->isComplete()) {
00877 # If the XForm has been successfully completed,
00878 # do the following case. Here, assuming you had a path
00879 # variable for where to go after finishing a form...
00880
00881
00882 $ixml = $xform->getInstanceXML();
00883 $simple = new SimpleXMLElement($ixml);
00884 $metadata = $simple->model->instance;
00885
00886
00887 $notMetadata = array('Name', 'submission_comments');
00888 foreach($notMetadata as $remove)
00889 unset($metadata->$remove);
00890
00891
00892 $metadata = $metadata->asXML();
00893 $metadataObj = new SDRMetadataObj($metadata);
00894
00895 $comment = $xform->getInstanceValue('//submission_comments');
00896 if (trim($comment) == '')
00897 $comment = $projectName . ' Submission';
00898
00899
00900
00901 $user = $SWAT->getProjectUser();
00902 $agent = SDRAgent::agentFromCSERDUser($user);
00903 if ($agent === false) {
00904 return self::FORM_ERROR;
00905 }
00906
00907 $id = ($cserdId == null) ? $xform->getInstanceValue('//Url') : $cserdId;
00908
00909 $result = self::submit($id,
00910 $metadataObj, $agent,
00911 $comment,
00912 $projectName);
00913
00914 if ($result === false) {
00915 return self::FORM_ERROR;
00916 }
00917
00918 $subject = "$projectName Metadata Submission";
00919 $mlr = new FormsMailer();
00920 $mlr->setFormMessage($ixml);
00921 $mlr->setSubject($subject);
00922 $mlr->addRecipient("valerie@shodor.org");
00923
00924
00925 if($mlr->sendMail()){
00926 return $result->cserdId;
00927 } else {
00928 return self::FORM_ERROR;
00929 }
00930 } else {
00931 # Load the HTML to display the form into your page
00932 $prm->load($xform->toHtml(), array('inFormat' => 'html'));
00933 return self::FORM_INPROCESS;
00934 }
00935
00936 }
00937
00938
00948 public static function buildMetadataForm($cserdId = null, $projectName, $versionId = null) {
00949
00950 $form = self::buildMetadataFormObject($cserdId, $projectName, $versionId);
00951 if ($form == null) {
00952 $form = new Form();
00953 return $form->buildForm("$projectName is Not Connected to Any Fields");
00954 }
00955
00956 if(count($cserdId) == null)
00957 return $form->buildForm('Submit New Metadata');
00958 else
00959 return $form->buildForm('Submit Changes');
00960 }
00961
00962
00972 public static function buildMetadataFormObject($cserdId = null, $projectName, $versionId = null) {
00973 $DBI = self::getDBI();
00974 $form = new Form();
00975 $metadata = null;
00976 if ($cserdId != null) {
00977 $metadata = SDRService::getMetadata($cserdId, $versionId);
00978 }
00979
00980
00981 $query = "SELECT SDRField.id as fieldId, SDRProjectField.required as required,
00982 SDRField.name as name, SDRField.description as description,
00983 SDRField.control as control, SDRField.type as type
00984 FROM SDRProject
00985 LEFT JOIN SDRProjectField on SDRProject.id = SDRProjectField.projectId
00986 LEFT JOIN SDRField on SDRProjectField.fieldId = SDRField.id
00987 WHERE SDRProject.name = '$projectName' and SDRField.editable = 1 order by SDRProjectField.indexOrder";
00988
00989 $result = $DBI->query($query);
00990
00991 if(count($result) == 0) return null;
00992
00993
00994
00995 $form->addInput("text", "$projectName Resource Documentation Form");
00996
00997 foreach($result as $res) {
00998 $required = ($res['required']=='true')?true:false;
00999
01000
01001 $default = ($metadata != null && $metadata->attributeExists($res['name'])) ? $metadata->$res['name'] : '';
01002
01003
01004 $valueOptions = array();
01005
01006 if ($res['control'] == 'select' || $res['control'] == 'select1' || $res['control']=='textlist') {
01007 $query = "SELECT SDRFieldValue.valueId, type, value
01008 FROM SDRFieldValue
01009 LEFT JOIN view_SDRValueSDRTextValue
01010 ON SDRFieldValue.valueId = id
01011 WHERE fieldId = $res[fieldId]
01012 ORDER BY value";
01013
01014 $values = $DBI->query($query);
01015
01016 if (!$values) {
01017 SErrorManager::setError('Query to get submission fields failed');
01018 return false;
01019 }
01020 while($valueEntry = $values->nextRow()) {
01021 array_push($valueOptions, array($valueEntry['value'], $valueEntry['value']));
01022 }
01023 }
01024
01025
01026 if ($res['control'] == 'textlist') {
01027 $res['type'] = 'textlist';
01028 $res['control'] = 'textarea';
01029 $res['description'] = '(one entry per line)<br/>'.$res['description'];
01030 if (is_array($default)) {
01031 $default = implode($default, "\n");
01032 }
01033 }
01034
01035
01036 $form->addInput($res['control'], str_replace('_', ' ', $res['name']).':', $res['name'], $res['type'], $required,
01037 $default, $valueOptions, '', $res['description']);
01038 }
01039
01040 $form->addTextarea('Submission comments:', 'submission_comments', 'paragraph', true, '', '', '',
01041 'Please summarize the changes you made to this version of the resource.');
01042 return $form;
01043 }
01044 }
01045 ?>