dmBridge PHP API
DMObject.php
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 DMObject extends DMModel implements DMURIAddressable {
00018 
00020    private $cdm_domdocument;
00023    private $children = array();
00025    private $collection;
00028    private $compound_type;
00030    private $config;
00032    private $data_store;
00034    private $date_created;
00036    private $date_updated;
00038    private $filename;
00040    private $image_width, $image_height;
00042    private $metadata = array();
00044    private $page;
00046    private $parent_obj;
00048    private $ptr;
00050    private $title;
00052    private $viewer;
00053 
00059    public static function exists(DMCollection $col, $ptr) {
00060       $xml = null;
00061       dmGetItemInfo($col->getAlias(), $ptr, $xml);
00062       return (bool) $xml;
00063    }
00064 
00074    public function __construct(DMCollection $collection, $ptr,
00075          DMDataStore $data_store, DMConfigIni $config) {
00076       $this->setCollection($collection);
00077       $this->setPtr($ptr);
00078       $this->data_store = $data_store;
00079       $this->config = $config;
00080    }
00081 
00087    public function __toString() {
00088       try {
00089          $value = ($this->getMetadata("title") instanceof DMDCElement)
00090             ? $this->getMetadata("title")->getValue()
00091             : $this->getCollection()->getAlias() . " " . $this->getPtr();
00092          return $value;
00093       } catch (Exception $e) {
00094          return $this->getCollection()->getAlias() . " " . $this->getPtr();
00095       }
00096    }
00097 
00106    public function getCdmURI() {
00107       $uri = clone DMHTTPRequest::getCurrent()->getURI()->getAbsoluteHostURI();
00108       if ($this->isCompound()) {
00109          $uri->setPath("/cdm4/document.php");
00110          $uri->addQueryValue("CISOROOT", $this->getCollection()->getAlias());
00111          $uri->addQueryValue("CISOPTR", $this->getPtr());
00112       } else if ($this->isChild()) {
00113          $uri->setPath("/cdm4/document.php");
00114          $uri->addQueryValue("CISOROOT", $this->getCollection()->getAlias());
00115          $uri->addQueryValue("CISOPTR", $this->getParent()->getPtr());
00116          $uri->addQueryValue("CISOSHOW", $this->getPtr());
00117       } else {
00118          $uri->setPath("/cdm4/item_viewer.php");
00119          $uri->addQueryValue("CISOROOT", $this->getCollection()->getAlias());
00120          $uri->addQueryValue("CISOPTR", $this->getPtr());
00121       }
00122       return $uri;
00123    }
00124 
00133    public function getChild($index) {
00134       $children = $this->getChildren();
00135       if (!array_key_exists($index, $children)) {
00136          return null;
00137       }
00138       return $children[$index];
00139    }
00140 
00144    public function isChild() {
00145       return ($this->getParent() instanceof DMObject);
00146    }
00147 
00154    public function getChildren() {
00155       if (count($this->children)) {
00156          return $this->children;
00157       }
00158 
00159       // get compound object structure
00160       $xml = null;
00161       dmGetCompoundObjectInfo(
00162          $this->getCollection()->getAlias(), $this->getPtr(), $xml);
00163       if (!strlen($xml)) {
00164          return array();
00165       }
00166 
00167       $dxml = new DOMDocument('1.0', 'utf-8');
00168       $dxml->loadXML($xml);
00169 
00170       // instantiate children
00171       foreach ($dxml->getElementsByTagName('pageptr') as $page) {
00172          $this->children[] = DMObjectFactory::getObject(
00173             $this->getCollection(), (int) $page->nodeValue);
00174       }
00175       return $this->children;
00176    }
00177 
00185    public final function hasChildren() {
00186       return (bool) count($this->getChildren());
00187    }
00188 
00192    public final function getCollection() {
00193       return $this->collection;
00194    }
00195 
00196    private function setCollection(DMCollection $collection) {
00197       $this->collection = $collection;
00198    }
00199 
00208    public function addComment(DMComment $comment) {
00209       return $this->data_store->addObjectComment($this, $comment);
00210    }
00211 
00216    public function hasComments() {
00217       return (count($this->data_store
00218             ->getApprovedCommentsForObject($this, 1, 1000)) > 0);
00219    }
00220 
00227    public function getCommentsFeedURL() {
00228       $params = "objects" . $this->getCollection()->getAlias()
00229          . "/" . $this->getPtr() . "/comments";
00230       return DMInternalURI::getURIWithParams($params, array(), "atom");
00231    }
00232 
00238    public function isCompound() {
00239       if (count($this->children)) {
00240          return true;
00241       }
00242 
00243       // get compound object structure
00244       $xml = "";
00245       dmGetCompoundObjectInfo(
00246          $this->getCollection()->getAlias(), $this->getPtr(), $xml);
00247       return (bool) strlen($xml);
00248    }
00249 
00255    public function getDateCreated() {
00256       if (!$this->date_created instanceof DMDateTime) {
00257          $dxml = $this->getCdmDOMDocument();
00258          $created = $dxml->getElementsByTagName("dmcreated")->item(0)->nodeValue;
00259          $this->date_created = new DMDateTime($created);
00260       }
00261       return $this->date_created;
00262    }
00263 
00269    public function getDateUpdated() {
00270       if (!$this->date_updated instanceof DMDateTime) {
00271          $dxml = $this->getCdmDOMDocument();
00272          $updated = $dxml->getElementsByTagName('dmmodified')->item(0)->nodeValue;
00273          $this->setDateUpdated(new DMDateTime($updated));
00274       }
00275       return $this->date_updated;
00276    }
00277 
00281    protected function setDateUpdated(DMDateTime $date) {
00282       $this->date_updated = $date;
00283    }
00284 
00291    public function equals($obj) {
00292       return (is_object($obj) && $obj instanceof DMObject
00293             && $this->getCollection()->getAlias()
00294             == $obj->getCollection()->getAlias()
00295             && $this->getPtr() == $obj->getPtr());
00296    }
00297 
00304    public function isFavorite() {
00305       $session = DMHTTPRequest::getCurrent()->getSession();
00306       foreach ($session->getAllFavorites() as $f) {
00307          if ((string) $f == (string) $this) {
00308             return true;
00309          }
00310       }
00311       return false;
00312    }
00313 
00320    public function getFeedURI() {
00321       return $this->getURI(DMBridgeComponent::TemplateEngine, "atom");
00322    }
00323 
00330    public function getField($nick) {
00331       return $this->getMetadata($nick);
00332    }
00333 
00340    public function addField(DMDCElement $elem) {
00341       $count = count($this->metadata);
00342       for ($i = 0; $i < $count; $i++) {
00343          if ($this->metadata[$i]->getNick() == $elem->getNick()) {
00344             $this->metadata[$i] = $elem;
00345             return;
00346          }
00347       }
00348       $this->metadata[] = $elem;
00349    }
00350 
00358    public function getFields() {
00359       return $this->getMetadata();
00360    }
00361 
00367    public function getFilename() {
00368       if (strlen($this->filename) < 1) {
00369          $this->instantiateFileProperties();
00370       }
00371       return basename($this->filename);
00372    }
00373 
00378    protected function setFilename($filename) {
00379       $this->filename = $filename;
00380    }
00381 
00387    public function getFileURL() {
00388       $base_uri = rtrim(DMHTTPRequest::getCurrent()->getURI()->getAbsoluteHostURI(), "/")
00389          . $this->config->getString("contentdm.showfile_exe.path");
00390       switch ($this->getCompoundType()) {
00391          case "Document-PDF":
00392             $qa = array(
00393                'CISOROOT' => $this->getCollection()->getAlias(),
00394                'CISOPTR' => ($this->isChild())
00395                   ? $this->getParent()->getPtr() : $this->getPtr(),
00396                'CISOPAGE' => $this->getPage()
00397             );
00398             $base_uri = rtrim(DMHTTPRequest::getCurrent()->getURI()->getAbsoluteHostURI(), "/")
00399                . $this->config->getString("contentdm.showpdf_exe.path");
00400             break;
00401          default:
00402             $ptr = ($this->isCompound())
00403                ? $this->getChild(0)->getPtr() : $this->getPtr();
00404             $qa = array(
00405                'CISOROOT' => $this->getCollection()->getAlias(),
00406                'CISOPTR' => $ptr
00407             );
00408             break;
00409       }
00410       return new DMURI(
00411             rtrim($base_uri, "/") . "?" . urldecode(http_build_query($qa)));
00412    }
00413 
00424    public function getFullText() {
00425       /* Check for the presence of a non-empty "full" field. The object itself
00426       may have one; or, it may be a compound object, one or more of whose
00427       children would have one. We need to check both cases. */
00428       $text = $this->getMetadata("full");
00429       // Does the object itself have a non-empty fulltext field?
00430       if (!$text instanceof DMDCElement || strlen($text->getValue()) < 1) {
00431          // no, so check children, if applicable
00432          if ($this->hasChildren()) {
00433             $text = $this->getChild(0)->getMetadata("full");
00434          }
00435       }
00436       return $text;
00437    }
00438 
00442    public function getHeight() {
00443       if ($this->image_height < 1) {
00444          $this->instantiateFileProperties();
00445       }
00446       return $this->image_height;
00447    }
00448 
00453    protected function setHeight($int) {
00454       $this->image_height = abs($int);
00455    }
00456 
00468    public function getImageURL($maxwidth, $maxheight, $x = 0, $y = 0,
00469          $rotate = 0) {
00470       // check width & height
00471       // cdm defaults to 500 for each, cropped from x & y, not scaled.
00472       if ($maxwidth <= 0) $maxwidth = 500;
00473       if ($maxheight <= 0) $maxheight = 500;
00474 
00475       // check x & y
00476       if ($x <= 0) $x = 0;
00477       if ($y <= 0) $y = 0;
00478 
00479       // check rotation
00480       if ($rotate <= -360 || $rotate >= 360) $rotate = null;
00481 
00482       // calculate display scale
00483       $h = $this->getHeight();
00484       $w = $this->getWidth();
00485       if (!$h || !$w) {
00486          return false;
00487       }
00488       $hscale = ($maxheight / $h) * 100;
00489       $wscale = ($maxwidth / $w) * 100;
00490       $scale = ($hscale < $wscale) ? $hscale : $wscale;
00491 
00492       // set up query array for http_build_query()
00493       $qs = array(
00494          'CISOROOT' => $this->getCollection()->getAlias(),
00495          'CISOPTR' => $this->getPtr(),
00496          'DMSCALE' => round($scale, 6),
00497          'DMWIDTH' => $maxwidth,
00498          'DMHEIGHT' => $maxheight,
00499          'DMX' => $x,
00500          'DMY' => $y,
00501          'DMROTATE' => $rotate
00502       );
00503 
00504       return new DMURI(rtrim(DMHTTPRequest::getCurrent()->getURI()->getAbsoluteHostURI(), "/")
00505          . $this->config->getString("contentdm.getimage_exe.path")
00506          . "?" . urldecode(http_build_query($qs)));
00507    }
00508 
00517    public function getMetadata($nick = null) {
00518       if (count($this->metadata) < 1) {
00519          $this->instantiateFields();
00520       }
00521       if (!is_null($nick)) {
00522          foreach ($this->metadata as $field) {
00523             if ($field->getNick() == $nick) {
00524                return $field;
00525             }
00526          }
00527          return null;
00528       }
00529       return $this->metadata;
00530    }
00531 
00540    public function getMediaType() {
00541       $default_type = new DMMediaType("unknown", "unknown");
00542 
00543       // extract filename extension
00544       $tmp = explode(".", $this->getFilename());
00545       if (count($tmp) < 2) {
00546          // no extension, abort
00547          return $default_type;
00548       }
00549 
00550       // If the object is compound, it will have an extension of ".cpd,"
00551       // which isn't very useful. So use the extension of its first child
00552       // instead.
00553       if ($this->isCompound()) {
00554          return $this->getChild(0)->getMediaType();
00555       }
00556 
00557       $ext = strtolower($tmp[count($tmp)-1]);
00558       if ($ext == "cpd") {
00559          if ($this->getCompoundType() == "Document-PDF") {
00560             $ext = "pdf";
00561          }
00562       }
00563 
00564       $type = DMMediaType::getTypeForExtension($ext);
00565       if ($type) {
00566          return $type;
00567       }
00568       return $default_type;
00569    }
00570 
00574    public function getPage() {
00575       if ($this->page > 0) {
00576          return $this->page;
00577       }
00578       $this->setChildProperties();
00579       return $this->page;
00580    }
00581 
00585    public function getParent() {
00586       if ($this->parent_obj instanceof DMObject) {
00587          return $this->parent_obj;
00588       }
00589       dmGetCollectionParameters($this->getCollection()->getAlias(), $name,
00590             $path);
00591       $result = GetParent($this->getCollection()->getAlias(), $this->getPtr(),
00592             $path);
00593       if ($result > -1) {
00594          $this->parent_obj = DMObjectFactory::getObject(
00595             $this->getCollection(), $result);
00596          return $this->parent_obj;
00597       }
00598       return null;
00599    }
00600 
00604    public function getPtr() {
00605       return $this->ptr;
00606    }
00607 
00611    private function setPtr($ptr) {
00612       $this->ptr = (int) $ptr;
00613    }
00614 
00622    public function addRating(DMRating $r) {
00623       $this->data_store->addObjectRating($this, $r);
00624    }
00625 
00634    public function getRating($out_of = 100, $decimal_places = 10) {
00635       if ($out_of <> round($out_of) || $out_of < 1) {
00636          return false;
00637       }
00638       $rating = $this->data_store->getRatingForObject($this);
00639       $rating = ($rating / 100) * $out_of;
00640       return (float) round($rating, $decimal_places);
00641    }
00642 
00650    public function getReferenceURL() {
00651       return rtrim(DMHTTPRequest::getCurrent()->getURI()->getAbsoluteHostURI(), '/') . '/u?'
00652          . $this->getCollection()->getAlias() . ',' . $this->getPtr();
00653    }
00654 
00663    public function addTag(DMTag $tag) {
00664       $this->data_store->addObjectTag($this, $tag);
00665    }
00666 
00672    public function getThumbURL() {
00673       $qs = array(
00674          'CISOROOT' => $this->getCollection()->getAlias(),
00675          'CISOPTR' => $this->getPtr()
00676       );
00677       return new DMURI(rtrim(DMHTTPRequest::getCurrent()->getURI()->getAbsoluteHostURI(), "/")
00678          . $this->config->getString("contentdm.thumbnail_exe.path")
00679          . "?" . urldecode(http_build_query($qs)));
00680    }
00681 
00687    public function getThumbnailURL() {
00688       return $this->getThumbURL();
00689    }
00690 
00698    public function getTitle() {
00699       if (strlen($this->title) > 0) {
00700          return $this->title;
00701       }
00702       $this->setChildProperties();
00703       return $this->title;
00704    }
00705 
00706 
00721    public function getURI($component = DMBridgeComponent::TemplateEngine,
00722          $representation = null,
00723          $resolve_links = true) {
00724       if ($resolve_links) {
00725          // if it's a ".url" object, it will link elsewhere
00726          if ($this->isURLType()) {
00727             return $this->getFileURL();
00728          }
00729       }
00730       if ($component == DMBridgeComponent::TemplateEngine
00731             && $representation == null) {
00732          $representation = "html";
00733       } else if ($component == DMBridgeComponent::HTTPAPI
00734             && $representation == null) {
00735          $representation = DMHTTPRequest::getCurrent()->getUri()->getExtension();
00736       }
00737       return DMInternalURI::getResourceURI(
00738             $component,
00739             "objects" . $this->getCollection()->getAlias()
00740                . "/" . $this->getPtr(),
00741             $representation);
00742    }
00743 
00747    public function isURLType() {
00748       $tmp = explode(".", $this->getFilename());
00749       return (count($tmp) && $tmp[count($tmp) - 1] == "url");
00750    }
00751 
00757    public function getViewer($width_override = null, $height_override = null) {
00758       if (!$this->viewer) {
00759          $def = $this->getCollection()->getViewerDefinitionForMediaType(
00760                $this->getMediaType());
00761          if (!$def) {
00762             $def = $this->getCollection()->getViewerDefinitionForMediaType(
00763                   new DMMediaType("unknown", "unknown"));
00764          }
00765          if (!$def) {
00766             return null;
00767          }
00768          $width = ($width_override) ? $width_override : $def->getWidth();
00769          $height = ($height_override) ? $height_override : $def->getHeight();
00770          $class = $def->getClass();
00771          $mime = $def->getMediaType();
00772          if (!class_exists($class)) {
00773             return null;
00774          }
00775          $this->viewer = new $class($this, $mime, $width, $height);
00776       }
00777       return $this->viewer;
00778    }
00779 
00783    public function getViewerClassName() {
00784       $def = $this->getCollection()->getViewerDefinitionForMediaType(
00785             $this->getMediaType());
00786       if (!$def) {
00787          $def = $this->getCollection()->getViewerDefinitionForMediaType(
00788                new DMMediaType("unknown", "unknown"));
00789       }
00790       if (!$def) {
00791          return null;
00792       }
00793       return $def->getClass();
00794    }
00795 
00799    public function getWidth() {
00800       if ($this->image_width < 1) {
00801          $this->instantiateFileProperties();
00802       }
00803       return $this->image_width;
00804    }
00805 
00809    protected function setWidth($int) {
00810       $this->image_width = abs($int);
00811    }
00812 
00816    private function getCdmDOMDocument() {
00817       if ($this->cdm_domdocument) {
00818          return $this->cdm_domdocument;
00819       }
00820       $xml = null;
00821       dmGetItemInfo($this->getCollection()->getAlias(), $this->getPtr(), $xml);
00822       if (!empty($xml)) {
00823          $this->cdm_domdocument = new DOMDocument("1.0", "utf-8");
00824          /* dmGetItemInfo() may return non-UTF-8 character data, or
00825           * apparently even non-any-character-set data, which loadXML()
00826           * will, understandably, not deal with in a friendly way. If it's
00827           * invalid UTF-8, we run DMString::clean() on it which may either
00828           * strip out invalid characters, or strip out non-ASCII characters,
00829           * depending on the PHP version. We shouldn't have to do that.
00830           * Bug report filed w/ OCLC Support 2010-03-04 by adolski,
00831           * SR#1-642143637.
00832           */
00833          if (!DMString::isUTF8($xml)) {
00834             $xml = DMString::clean($xml);
00835          }
00836          $this->cdm_domdocument->loadXML($xml);
00837          return $this->cdm_domdocument;
00838       } else {
00839          throw new DMUnavailableModelException(
00840                DMLocalizedString::getString("NONEXISTENT_OBJECT"));
00841       }
00842    }
00843 
00844    private function getCompoundType() {
00845       if ($this->compound_type) {
00846          return $this->compound_type;
00847       }
00848       if ($this->isChild()) {
00849          $this->setChildProperties();
00850       }
00851 
00852       // get compound object structure
00853       dmGetCompoundObjectInfo(
00854          $this->getCollection()->getAlias(),
00855          $this->isChild() ? $this->getParent()->getPtr() : $this->getPtr(),
00856          $xml);
00857       if (!strlen($xml)) {
00858          return null;
00859       }
00860 
00861       $dxml = new DOMDocument("1.0", "utf-8");
00862       $dxml->loadXML($xml);
00863 
00864       $this->compound_type = $dxml->getElementsByTagName("type")->item(0)
00865             ->nodeValue;
00866       return $this->compound_type;
00867    }
00868 
00872    private function instantiateFields() {
00873       $dxml = $this->getCdmDOMDocument();
00874       // create DMDCElement objects from XML structure
00875       $skip_fields = array('find', 'dmaccess', 'dmcreated', 'dmmodified',
00876          'dmoclcno', 'dmrecord');
00877       $children = $dxml->documentElement->childNodes;
00878       if (!$children instanceof DOMNodeList) {
00879          return;
00880       }
00881       foreach ($children as $node) {
00882          if (in_array($node->nodeName, $skip_fields)) {
00883             continue;
00884          }
00885          $f = $this->getCollection()->getField($node->nodeName);
00886          if ($f instanceof DMDCElement) {
00887             $m = clone $f;
00888             $m->setValue((string) $node->nodeValue);
00889             $this->metadata[] = $m;
00890             unset($m, $f);
00891          }
00892       }
00893    }
00894 
00898    private function instantiateFileProperties() {
00899       $filename = $type = $width = $height = null;
00900       dmGetImageInfo($this->getCollection()->getAlias(),
00901          $this->getPtr(), $filename, $type, $width, $height);
00902       $this->setFilename($filename);
00903       $this->setHeight($height);
00904       $this->setWidth($width);
00905    }
00906 
00911    private function setChildProperties() {
00912       $xml = "";
00913       dmGetCollectionParameters($this->getCollection()->getAlias(), $name,
00914             $path);
00915       $result = GetParent($this->getCollection()->getAlias(),
00916             $this->getPtr(), $path);
00917       dmGetCompoundObjectInfo($this->getCollection()->getAlias(), $result,
00918             $xml);
00919       if (!$xml) {
00920          return;
00921       }
00922 
00923       // dmGetCompoundObjectInfo() may return invalid UTF-8;
00924       // see getCdmDOMDocument()
00925       if (!DMString::isUTF8($xml)) {
00926          $xml = DMString::clean($xml);
00927       }
00928       $dxml = new DOMDocument('1.0', 'utf-8');
00929       $dxml->loadXML($xml);
00930       $page = 1;
00931       $this->compound_type = $dxml->documentElement
00932             ->getElementsByTagName('type')->item(0)->nodeValue;
00933       foreach ($dxml->documentElement->getElementsByTagName('page') as $p) {
00934          if ($p->getElementsByTagName('pageptr')->item(0)->nodeValue
00935                == $this->getPtr()) {
00936             $this->page = (int) $page;
00937             $this->title = $p->getElementsByTagName('pagetitle')->item(0)
00938                   ->nodeValue;
00939             break;
00940          }
00941          $page++;
00942       }
00943    }
00944 
00945 }
 All Data Structures Functions Variables