dmBridge 2.1.1 User's Manual

Alex Dolski

Web & Digitization Application Developer
University of Nevada, Las Vegas Libraries

Table of Contents

Preface
I. Introduction
1. Important CONTENTdm® concepts
Architecture
Objects and collections
Persistence & retrieval
Authentication
Web templates
Administration module
APIs & custom development
2. History & overview of dmBridge
II. Installation & upgrading
3. System requirements
4. Installation
Data store setup
SQLite
MySQL
Main setup
Web server URL rewriting
Initial configuration
Security considerations
5. Upgrading
From version 1.x
Web template changes
From version 2.0
New requirements
Upgrade steps
From version 2.1
Upgrade steps
6. Optional features
Reference URL redirection
III. Using dmBridge
7. Template engine
Template sets
Physical structure
Supported markup languages
Collection access
Custom template sets
Views
Error view
Favorites view
Object view
Object-results view
Results view
Search view
Login view
URI routes
Content representations
Using the PHP API in the templates
8. Control Panel
Basic Setup
Modules
Comments
Configure
Moderate
Search
Statistics
Ratings
Configure
Statistics
Tags
Configure
Moderate
View All
Statistics
Collections
View All
URL Redirection
Template Sets
Add
View All
Feeds
CQR
9. User authentication
10. Commenting
11. Rating
12. Tagging
13. Modules
Installing modules
Upgrading modules
14. Custom queries and results (CQR)
15. Search suggestions
16. Term clouds
17. Sitemaps
18. Highlighted object
19. Random objects
20. Spatial objects
Importing spatial object metadata
Embedding maps in the templates
Spatial searching
Accessing spatial data programmatically
Via the HTTP API
Via the PHP API
IV. Developing with dmBridge
21. PHP API
22. Template helpers
Introduction
Writing template helpers
A simple template helper
Using custom stylesheets and JavaScripts
23. Object viewers
24. Modules
Module guidelines
Module architecture
Environment bootstrapping
Exposing URI routes
Controllers
Adding HTTP API documentation
Adding sections to the Control Panel
Using custom template helpers
Using models
Persistence
Localization
25. HTTP API

List of Figures

1.1. High-level architecture of CONTENTdm® 5.x
1.2. High-level architecture of CONTENTdm® 6.x
2.1. High-level architecture of a dmBridge repository
2.2. Example of results view in the dmBridge MVC architecture
7.1. The finding process in dmBridge

Preface

This manual is written from the perspective of a software developer, which is likely to be different from that of a web developer, librarian, or other role. Please bear with us and feel free to suggest changes or improvements by posting in the dmBridge discussion group, a link to which is available on the dmBridge home page. This is the primary communication hub for dmBridge users and developers.

[Note]Note

Throughout this manual, folder paths are written with forward slashes (/), Unix-style. Windows users should interpret these as backslashes (\).

[Note]Note

Throughout this manual, dmBridge URLs are written as if dmBridge is installed in a directory called /dm in the web server's document root.

[Note]Note

Throughout this manual, "URLs" are often called "URIs," for the sake of consistency with contemporary W3C terminology. Practically speaking, these terms are usually synonomous.

dmBridge is available under the MIT License, a copy of which is included in the dmBridge software distribution in the LICENSE.txt file.

Part I. Introduction

Chapter 1. Important CONTENTdm® concepts

CONTENTdm® could be thought of as consisting of two main "facets": the "librarian" side, consisting of metadata authoring; and the "public" side, consisting of the web templates and the infastructure that drives them. dmBridge has nothing to do with the former, but a prerequisite of making sense of dmBridge is understanding the basics of the latter.

[Note]Note

This information has been accumulated from personal experience and is not authoritative. For definitive information about CONTENTdm®, contact OCLC.

Architecture

The architecture of CONTENTdm® has changed somewhat from version 5 to 6. Most notable has been the addition of a separate "website" component (Figure 1.1, “High-level architecture of CONTENTdm® 5.x”, Figure 1.2, “High-level architecture of CONTENTdm® 6.x”).

Figure 1.1. High-level architecture of CONTENTdm® 5.x

High-level architecture of CONTENTdm 5.x
[Note]Note

The separate web servers indicate components that can, but do not have to, run on separate web servers. dmBridge is grayed-out to indicate that it is optional.


Figure 1.2. High-level architecture of CONTENTdm® 6.x

High-level architecture of CONTENTdm 6.x
[Note]Note

The separate web servers indicate components that can, but do not have to, run on separate web servers. dmBridge is grayed-out to indicate that it is optional.


Objects and collections

CONTENTdm® is a digital object repository system based around the concepts of "objects" (usually called "items") and "collections." An object is a combination of digital primary data - typically in the form of a file on disk - and metadata. It must reside in a collection. It has an ascending-integer identifier called a "pointer" ("CISOPTR"), which will uniquely identify it within a collection; but this is not a global identifier, as objects in different collections may have the same pointers. To globally identify an object, the combination of a collection alias (see below) and pointer must be used.

Collections can contain any number of objects, but they cannot contain other collections. A collection has a name and a unique identifier, called an "alias" (or "CISOROOT"), which is a brief string prefixed with a slash. It has a metadata template, which defines the set of Dublin Core metadata elements that are available to be used by objects in the collection and how they are to be sorted, searched, named, mapped, and so on.

Object metadata in CONTENTdm® is compatible with the Dublin Core and VRA Core metadata standards.

CONTENTdm® supports a special type of object called a compound object. This is actually an amalgamation of several independent objects into one whole. A compound object consists of a single "master" or "parent" object associated with zero or more "pages," which are themselves objects.

Persistence & retrieval

CONTENTdm® uses a proprietary, purpose-built, non-relational database for persistence of all metadata, collection data, and indexes. There is no OCLC-approved way of accessing this database directly. Object files themselves are not stored in the database and instead are stored as-is inside a managed folder structure. As of version 2.1, dmBridge accesses thumbnail images and object files directly from the filesystem, without going through CONTENTdm®.

All CONTENTdm® objects have a thumbnail image, which is a highly compressed JPEG image constrained to 160 pixels on a side. A thumbnail image can be accessed in a typical installation at the following URI:

http://my_cdm_server/cgi-bin/thumbnail.exe?CISOROOT=[alias]&CISOPTR=[pointer]

The file of a CONTENTdm® object can be accessed at the following URI:

http://my_cdm_server/cgi-bin/showfile.exe?CISOROOT=[alias]&CISOPTR=[pointer]

This includes full-sized images, for objects that have one.

For image-based objects, a cropped image tile can be downloaded at the following URI:

http://my_cdm_server/cgi-bin/getimage.exe?CISOROOT=[alias]&CISOPTR=[pointer]&DMHEIGHT=[height] &DMWIDTH=[width]&DMX=[offset]&DMY=[offset]&DMSCALE=[0-100]&DMROTATE=[0-360]

These tiles are generated on-the-fly.

Authentication

CONTENTdm® uses HTTP for authentication (Basic or Digest). This is handled by a bundled CGI executable. When authentication is successful, the CGI executable will set a session cookie which is used for further authorization in the PHP environment. The access control list (often an .htaccess file) is managed by the web server.

Web templates

In versions 4 and 5, the web templates, typically located at http://my_cdm_server/cdm4/, were where all of CONTENTdm®'s public dynamic HTML resided. These were not really "templates," per se, but were instead crude amalgamations of PHP, HTML, JavaScript, and CSS. These templates handled all aspects of CONTENTdm®'s web display, and also processed input from URI query parameters for searching etc. The web templates relied on the CONTENTdm® PHP API.

CONTENTdm® 6 delivered a new web front-end. Rather than communicating with the CONTENTdm® server via the PHP API, it now communicates via HTTP. The CONTENTdm® 6 web front-end is built using the Zend Framework and addresses many of the complaints regarding the previous web templates.

Administration module

The administration module enables web-based administration of the CONTENTdm® system. It is normally available at http://my_cdm_server/cgi-bin/admin/start.exe. dmBridge does not interface directly with this component, but settings made in it will propagate to dmBridge.

APIs & custom development

Before version 6.x, the only way of accessing information from CONTENTdm® programmatically was via its PHP API. This is a simple procedural API consisting of a few dozen PHP functions. The CONTENTdm® PHP API is enabled by a proprietary PHP extension, which bridges the PHP environment with the CONTENTdm® system which is distributed as a number of compiled binaries. The dmBridge PHP API is, in part, an abstraction of this API.

Version 6.x of CONTENTdm® delivered a new web-based API. This is an RPC-style API that essentially maps PHP API functions to HTTP calls. dmBridge does not use this API as it already provides its own HTTP API.

[Note]Note

CONTENTdm® PHP API documentation is available to CONTENTdm® customers by request from OCLC.

CONTENTdm® does not have a provision for modules, extensions, or any other way of altering its functionality. Any customization must therefore be implemented outside it, and if it needs to persist data, it must do so externally from CONTENTdm®. This imposes certain limitations; for example, custom persistent data in a relational database like MySQL cannot be searched in conjunction with CONTENTdm® metadata because the CONTENTdm® search engine cannot "see" it, and vice versa.

Chapter 2. History & overview of dmBridge

The dmBridge project began in May 2008 as a few PHP classes supporting a set of rudimentary web templates. Since then, its scope has expanded with the goal of improving customizability and quality of web-based digital collections presentation; and providing a full-featured framework for programmatic access to digital repository content.

dmBridge is a layer on top of the CONTENTdm® digital asset management system that effectively replaces its "web templates" component and adds a number of other features (Figure 2.1, “High-level architecture of a dmBridge repository”). In its current form, dmBridge cannot function without CONTENTdm®.

Figure 2.1. High-level architecture of a dmBridge repository

High-level architecture of a dmBridge repository

Although dmBridge is capable of replacing many CONTENTdm® features, it does not override them, which is to say that it does not interfere with any aspects of CONTENTdm® operation, so both can operate normally side-by-side. dmBridge does not modify any CONTENTdm® files or otherwise affect it in any way. The figure below illustrates a typical web server folder structure with both CONTENTdm® and dmBridge installed side-by-side.

/1
    cdm4/2
    cgi-bin/3
    dm/4
        

1

The web server's document root, which is typically mapped to a site's base URL (e.g. http://digital.library.unlv.edu/). Other files can be stored here besides the ones listed.

2

The CONTENTdm® 5.x web templates.

3

Web server CGI executables. These enable many CONTENTdm® features.

4

The default location of the dmBridge files. This folder can be moved or renamed.

From a user's perspective, dmBridge consists of three main components:

  • A template engine, which drives one or more sets of custom web templates.

  • A RESTful HTTP API, which enables programmatic remote access.

  • A Control Panel, which serves as a convenient central point of administration.

dmBridge employs a Model-View-Controller (MVC) design. In the template engine, the views are customizable HTML templates; in the HTTP API, they are built-in XML/JSON output routines. Views and controllers are separate for each main component, but models are shared by all three. Models can also be used in the context of the PHP API.

Figure 2.2. Example of results view in the dmBridge MVC architecture

Example of results view in the dmBridge MVC architecture

Part II. Installation & upgrading

Chapter 3. System requirements

In contrast to version 1.x, which was a client-server system, dmBridge 2.x is a monolithic system which must run on the same web server and in the same PHP environment as CONTENTdm®. dmBridge requires all of the following:

[Caution]Caution

dmBridge is developed at a self-hosted institution which has no access to the OCLC hosted environment. Hosted users should inquire with OCLC to find out if their hosted environment meets the above requirements.

Chapter 4. Installation

[Note]Note

This section applies only to first-time installation. If you are upgrading, skip to Chapter 5, Upgrading.

Data store setup

In contract to version 1.x, a data store is required in version 2.0. dmBridge currently supports two different data stores:

SQLite 3 (default)

A simple file-based database that is fast, reliable, and easy to configure. Recommended if you don't have access to a MySQL server.

[Caution]Caution

The SQLite database must reside on the local filesystem. SQLite will not work over an NFS or CIFS share.

MySQL 4.x and above

Requires the PHP PDO extension.

[Note]Note

PostgreSQL support was present in version 1.x, but has been removed in version 2 due to lack of use.

SQLite

SQLite is often pre-installed in many Linux distributions. If you are running Linux, search your system for an executable named sqlite. If that fails, check your package manager.

If SQLite is available, proceed to the section called “Main setup”. If not, you will have to download and install it manually; see the SQLite home page for more information.

MySQL

[Caution]Caution

The MySQL options is intended for organizations that already have a MySQL server set up and available, and have someone on staff who knows the basics of administering it. If this is not the case, you should use SQLite instead. Installation instructions for the MySQL database itself will not be provided here; we will assume it is already up and running at your site.

Configuring with PHP

MySQL requires the PHP PDO extension for use with dmBridge. To verify that this is installed, run phpinfo():

<?php phpinfo(); ?>

And search for a "PDO" section. If you don't also see a "pdo_mysql" or "pdo_sqlite" section (depending on your database), you will need to install the appropriate PDO driver. Depending on your operating system, this may be available as a package, or you may have to install it from PECL:

# pecl install pdo_mysql

Creating the database

dmBridge does not have a tool for creating the database itself; you will have to do this manually. However, you should not have to create the database tables; see the next section.

Enabling in dmBridge

The final step is to enter the database connection settings. This is done in config.ini by setting the necessary parameters beginning with database.

If the database does not already have the necessary tables, dmBridge will attempt to create them. If this should happen to fail for some reason, you must manually execute (and if necessary, tweak) one of the sample SQL scripts provided in the dm/includes/data/schema folder.

Main setup

  1. Extract the downloaded dmBridge distribution. This will result in a single folder called dmbridge-x.x.x.

  2. Rename the dmbridge-x.x.x folder to dm.

  3. Move the dm folder into your CONTENTdm® web server's document root. (This is the same place where your current cdm4 and dmscripts folders reside.

  4. Copy dm/data/config.default.xml to dm/data/config.xml.

  5. Move the dm/data folder somewhere where it is not web-accessible. This may be anywhere outside your web server's document root; or you may be able to "lock down" a specific directory with a web server configuration directive.

    [Warning]Warning

    Failure to complete this step means that your database password and/or social data may be exposed to the public.

  6. Copy config.default.ini to config.ini.

  7. In config.ini, set dmbridge.data_path to the new absolute path of the dm/data folder. If you are unsure of the absolute path, create an empty PHP script in the same folder, type the following code into it, and load it in a web browser:

    <?php die(dirname(__FILE__)); ?>

    This will show you the full path to your dmBridge folder. Adjust it appropriately to point to your data folder instead. Make sure to change any backslashes to forward slashes.

  8. Ensure the permissions on the dm/data folder are set so that the web server process has read/write access to all of the files and folders inside it.

  9. If using CONTENTdm® 5.x, open Content5/docs/dmscripts/DMSystem.php and find the following around line 1811:

    print("<!-- $url //-->\n");

    And comment it out by appending two slashes to it:

    // print("<!-- $url //-->\n");

  10. Edit config.ini appropriately. Each setting is documented within the file and will not be discussed here.

  11. In a web browser, navigate to the following URI and verify that it outputs XML without any <dmException> elements showing up (you may have to view the page source to see it):

    http://my_cdm_server/dm/api/collections.xml

  12. Modify robots.txt appropriately, if necessary.

dmBridge is now installed, but it is not yet configured. This will be done in the next section.

Web server URL rewriting

In dmBridge 1.x, "clean URLs" were optional. In version 2.x, they are required. In order for them to work, the web server must be configured to support URL rewriting. This is easy to get working on both Apache and IIS. On Apache, it requires the mod_rewrite module to be enabled in httpd.conf. On IIS, there are a few different options, one of which is ISAPI Rewrite. The free Lite version does not support .htaccess files, but it's easy enough to add global rules instead. An example set:

RewriteCond %{REQUEST_FILENAME} !-f [OR]
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/dm(.*)$ /dm/index.php?q=$1 [L,QSA]

This would get saved in C:\Program Files\Helicon\ISAPI_Rewrite3\httpd.conf. Naturally, you will need to change /dm to the path to your dmBridge instance.

dmBridge includes an .htaccess file which the web server should read (if it is configured to do so; in Apache, see the AllowOverride directive in httpd.conf). If the web server is configured to read .htaccess files, then this file should "just work" and there should be no further configuration necessary.

You can use the same rules in your Apache httpd.conf file as well if you can't or don't want to use .htaccess files.

Initial configuration

  1. Navigate to the Control Panel, located at the following URI:

    http://my_cdm_server/dm/admin

  2. In the Basic Setup section, set your institution name.

  3. In the Feeds section, set your feed settings.

  4. In the Collections section, click View All. Click "Edit" next to the Default Collection. Choose a template set and then click the Change button at the bottom of the page.

  5. In the Template Sets section, click View All. Click "Edit" next to each template set. Choose the default and allowed collections for each template set.

dmBridge is now up and running. Proceed to Part III, “Using dmBridge” for information on utilization and customization.

Security considerations

By default, all components of dmBridge are fully exposed to the public. This gives anyone on the Internet the ability to use data from your digital collections in their own applications, mashups, etc. This might seem cause for alarm, but actually, everyone on the Internet has already had this ability, either by harvesting your OAI-PMH content, or by screen-scraping your templates. Little, if any, information that was previously private is made public by the dmBridge HTTP API; it has just been made more convenient to access programmatically.

Still, some users might wish to restrict their HTTP API, for whatever reason. There is no built-in provision for access controls built into the HTTP API component itself. We recommend that you use the access control features built into your web server to restrict access to URI paths matching the HTTP API based on IP address. (All HTTP API URI paths begin with api.)

Chapter 5. Upgrading

The sections in this chapter are ordered ascending by version. When upgrading, you should start at the version you're currently using, and read and implement the instructions in each section in order.

From version 1.x

[Caution]Caution

Before doing anything else, ensure your environment meets the changed system requirements.

  1. Back up your existing dmBridge folder, or the folders of the individual components if you moved them out of their enclosing folder. The list of component folders includes api, dmctrl, objects, and data, any of which you may have renamed.

  2. Delete all of the above folders except data.

  3. go through the initial setup, using your existing data folder as your new data folder.

  4. Upgrade your web templates.

Web template changes

Template helpers (previously called "extensions") are largely the same since version 1.x, but the way to invoke them has changed. To update your templates, you will need to comb through the .html.php files in your template sets and change the call on the left to the call on the right. The method parameters (everything inside the parentheses) can remain unchanged.

Change... To... Notes
Draw::atomFeedURL() $view->getHelper()->getHtmlAtomFeedURL()
Draw::collectionsAsPulldown() $view->getHelper()->getHtmlCollectionsAsPulldown() No longer requires JavaScript
Draw::downloadImageLink() $view->getHelper()->getHtmlDownloadImageLink()
Draw::exception() $view->getHelper()->getHtmlException()
Draw::favoritesPageURL() $view->getFavoritesView()->getURI()
Draw::flash() $view->getFlash()
Draw::formattedFlash() $view->getHelper()->getHtmlFormattedFlash()
Draw::isFlash() $view->isFlash()
Draw::loadTime() $view->getLoadTime()
Draw::loginPageLink() $view->getHelper()->getHtmlLoginPageLink()
Draw::loginPageURL() $view->getLoginView()->getURI()
Draw::logoutURL() $view->getLogoutURL()
Draw::rssFeedURL() RSS feed support is no longer available.
Draw::searchPageURL() $view->getSearchView()->getURI()
Draw::tagsAsCloud() $view->getHelper()->getHtmlTagsAsCloud()
Draw::termLinkedToSearch() $view->getHelper()->getHtmlTermLinkedToSearch() Method parameters have changed.
Draw::vocabularyAsCloud() $view->getHelper()->getHtmlVocabularyAsCloud()
Draw::vocabularyAsList() $view->getHelper()->getHtmlVocabularyAsList()
Draw::vocabularyForSelect() $view->getHelper()->getHtmlVocabularyAsSelect() This method now returns an enclosing <select> element around its returned <option> elements.
ObjectDraw::addFavoriteButton() $view->getHelper()->getHtmlAddFavoriteButton()
ObjectDraw::childLinksAsList() $view->getHelper()->getHtmlChildLinksAsList()
ObjectDraw::childLinksAsPulldown() $view->getHelper()->getHtmlChildLinksAsPulldown()
ObjectDraw::commentsSection() $view->getHelper()->getHtmlCommentsSection()
ObjectDraw::compoundObjectSearchForm() $view->getHelper()->getHtmlCompoundObjectSearchForm()
ObjectDraw::compoundObjectPageNumbersInSearchResultsAsString() $view->getHelper()->getHtmlCompoundObjectPageNumbersInSearchResultsAsString()
ObjectDraw::compoundPageFlipLinks() $view->getHelper()->getHtmlCompoundPageFlipLinks()
ObjectDraw::highlightedFullText() $view->getHelper()->getHtmlHighlightedFullText()
ObjectDraw::loadTime() $view->getLoadTime()
ObjectDraw::metadataAsDL() $view->getHelper()->getHtmlMetadataAsDL()
ObjectDraw::metadataAsMetaTags() $view->getHelper()->getHtmlMetadataAsMetaTags()
ObjectDraw::previousNextLinks() $view->getHelper()->getHtmlPreviousNextLinks() The $results_text parameter has been removed.
ObjectDraw::ratingsSection() $view->getHelper()->getHtmlRatingsSection()
ObjectDraw::resultsAsUL() $view->getHelper()->getHtmlResultsAsUL()
ObjectDraw::taggingSection() $view->getHelper()->getHtmlTaggingSection() No longer returns a list of tags; use $view->getHelper()->getHtmlTagsAsCloud() for that.
ObjectDraw::viewer() $view->getHelper()->getHtmlViewer()
ObjectResultsDraw::loadTime() $view->getLoadTime()
ObjectResultsDraw::numResults() $view->getQuery()->getNumResults()
ObjectResultsDraw::pageLinks() $view->getHelper()->getHtmlPageLinks()
ObjectResultsDraw::results() $view->getHelper()->getHtmlResults()
ObjectResultsDraw::searchTerms() $view->getHelper()->getHtmlSearchTerms()
ResultsDraw::facetsAsUL() $view->getHelper()->getHtmlFacetsAsUL()
ResultsDraw::linkedSuggestion() $view->getHelper()->getHtmlLinkedSuggestion()
ResultsDraw::loadTime() $view->getLoadTime()
ResultsDraw::numResults() $view->getQuery()->getNumResults()
ResultsDraw::pageLinks() $view->getHelper()->getHtmlPageLinks()
ResultsDraw::results() $view->getHelper()->getHtmlResults()
ResultsDraw::resultsAsGrid() $view->getHelper()->getHtmlResultsAsGrid()
ResultsDraw::resultsAsList() $view->getHelper()->getHtmlResultsAsList()
ResultsDraw::resultsAsTiles() $view->getHelper()->getHtmlResultsAsTiles()
ResultsDraw::searchTerms() $view->getHelper()->getHtmlSearchTerms()
ResultsDraw::sortLinksAsUL() $view->getHelper()->getHtmlSortLinksAsUL()
ResultsDraw::thumbsToggleLink() Support for disabling thumbnails in results view has been removed
ResultsDraw::viewLinks() $view->getHelper()->getHtmlViewLinks() Method parameters have changed.
SearchDraw::dateSearch() $view->getHelper()->getHtmlDateSearch()
SearchDraw::fieldSearch() $view->getHelper()->getHtmlFieldSearch()
SearchDraw::loadTime() $view->getLoadTime()
SearchDraw::proximitySearch() $view->getHelper()->getHtmlProximitySearch()
dmCart::getInstance()->getAccessibleObjects() $view->getAccessibleFavorites()
dmCart::getInstance()->getNumAccessibleObjects() count($view->getAccessibleFavorites())
dmObject::getCurrent() $view->getObject()
dmQuery::getCurrent()->areSearchTerms() $view->getQuery()->arePredicates()
dmQuery::getCurrent()->getRecordURL() $view->getObject()->getURI()
dmQuery::getCurrent()->getSearchTerms() $view->getQuery()->getPredicates()
dmQuery::getCurrent()->getURL("rdf") RDF support is no longer available.
dmQuery::getCurrent()->getURL("atom") $view->getQuery()->getURI("atom")
dmQuery::getCurrent()->getURL("rss") RSS feed support is no longer available.
dmTemplateSet::getCurrent() $view->getTemplate()->getTemplateSet()
instanceof Query instanceof DMQuery

Also, you will need to add the following template helper calls to your templates:

Code Location
<?php echo $view->getHelper()->getHtmlHeadScriptTags() ?> Inside the head tag
<?php echo $view->getHelper()->getHtmlStylesheetTags() ?> Inside the head tag
<?php echo $view->getHelper()->getHtmlMetaTags() ?> Inside the head tag
<?php echo $view->getHelper()->getHtmlBodyScriptTags() ?> Inside the body element, near the bottom of the page

From version 2.0

New requirements

dmBridge now requires the Ghostscript software to be installed on the server. (If it is not, the new DMPaginatedPDFViewer will not work, though the rest of dmBridge will function normally.)

Upgrade steps

  1. Back up your existing dmBridge folder.

  2. Add the following new keys to your config.ini file:

    dmbridge.ghostscript_path

    The absolute path to the gs program.

    contentdm.collections.pathname

    The absolute path to the folder containing the CONTENTdm® collections.

  3. Remove the following no-longer-used keys from your config.ini file:

    • contentdm.showfile_exe.path

  4. If you wish to use the new DMPaginatedPDFViewer as a PDF viewer, associate it with application/pdf files in the Collections section of the Control Panel.

  5. If you wish to use the new DMMonocle2Viewer instead of the DMMonocleViewer, associate it with the common image types - image/jpeg, image/tiff, image/jp2, etc. - in the Collections section of the Control Panel.

    [Caution]Caution

    The DMMonocleViewer is deprecated and will be removed from a future version of dmBridge. Please upgrade at your earliest convenience.

  6. If you have created any custom object viewers:

    1. Implement the new DMObjectViewerDelegate::isLowBandwidthCompatible() method in each one. See Chapter 23, Object viewers for more information.

    2. Remove all arguments from the constructor, if defined.

From version 2.1

Upgrade steps

  1. Back up your existing dmBridge folder.

  2. If you removed these keys from your config.ini file when upgrading to 2.0, please add them back:

    • contentdm.showpdf_exe.path

    • contentdm.thumbnail_exe.path

Chapter 6. Optional features

Table of Contents

Reference URL redirection

Steps involving optional features should be followed whether installing or upgrading.

Reference URL redirection

Reference URLs are persistent URLs for CONTENTdm® objects that look like this:

http://digital.library.unlv.edu/u?/hughes,87

Notice how the page on which you end up has a different URL than the reference URL. Accessing a reference URL redirects you to the CONTENTdm® template corresponding with that object. dmBridge, however, is going to use a different template, with a different URL. You will, therefore, want to selectively redirect your reference URLs depending on which system you want the object to appear in. The way to do this is by installing the provided replacement reference URL routing script.

The default reference URL routing script resides at: /u/index.php (relative to your CONTENTdm® server's document root). The replacement script is bundled in the dm/u/ folder. To enable it, follow these instructions:

  1. Make a backup of /u/index.php

  2. Copy dm/u/index.php to /u/index.php.

  3. Open /u/index.php and edit DMBRIDGE_ROOT, if necessary.

  4. Set up your redirects in the Reference URLs section of the Control Panel.

Part III. Using dmBridge

Chapter 7. Template engine

The dmBridge template engine attempts to strike a balance between ease of use, advanced customization potential, and upgrade-safety (meaning that underlying implementation changes in either dmBridge or CONTENTdm® won't break your page templates). The high-level HTML layout is left entirely up to the web designer, while some smaller bits - rendered by the template helpers - render HTML in a fixed structure that can be styled, but not customized. (This is the price to pay for the ease of being able to use "one-liners" to call up sophisticated functionality.) The default functionality of any of the template helper methods can be overridden by custom helpers, but this is generally a job for a programmer.

In practice, even without custom helpers, the template development process is much more flexible than that for the CONTENTdm® templates. (Originally, this was the number-one design priority for dmBridge.) However, it is also completely different, so there is a necessary learning curve.

Template sets

A single set of dmBridge templates can be used with a single collection, multiple collections, or all collections. Conventionally, a "single collection" set of templates would be customized for that collection, and an "all-collections" set of templates would be styled to harmonize with the digital collections department or organization. That's just an idea, and you are free to do whatever you want. It is easy to reassign which collections appear in which set of templates at any time via the Template Sets section of the Control Panel.

dmBridge templates can coexist peacefully with CONTENTdm® default templates, as the two do not interfere with each other.

[Caution]Caution

You should never delete your default templates, as they are required by the CONTENTdm® administration module.

Physical structure

Template sets are self-contained in their own folders, located inside the dm/templates folder. The required elements of a template set folder are as follows:

templates/
    error/
        view.html.php1
    favorite/
        index.html.php2
    object/
        compound_results.html.php3
        no_results.html.php4
        results_faceted.html.php5
        results.html.php6
        view_compound.html.php7
        view_simple.html.php8
    search/
        index.html.php9
    user/
        login.html.php10

1

Error view

2

Favorites view

3

Object results view

4

"No results" view, resulting from a search that returned no results

5

Results view, when facets are available for display

6

Results view, when no facets are available for display

7

Compound object view

8

"Simple", non-compound object view

9

Search view. Note that this displays only the search form; results are displayed in one of the object results templates.

10

Login view

These are only the required elements of a template set. It is perfectly acceptable to add additional folders containing any other kind of files used by the template set. For example, many template sets will include folders such as a top-level images and/or scripts folder; additional HTML/PHP files to include; etc.

Supported markup languages

Although the template author is theoretically free to write templates using any markup language, the dmBridge template helper methods currently return markup exclusively in HTML. This means:

  1. The templates themselves must be written in HTML in order to be valid.

  2. The templates must be served with a Content-Type header of "text/html."

Often, web pages are written in XHTML and served with a Content-Type of "text/html" -- an improper configuration that causes them to be parsed as HTML. This will "work" in that browsers will render the resulting pages, but the end result will be little different from serving plain HTML.

It is a goal of dmBridge that all template helper methods should pass W3C validation. This is not always achieved. But the more important thing is that the markup is at least good enough to trigger web browsers' "standards mode," which optimizes the accuracy and compatibility with which they will render the markup.

HTML5

HTML5 is an evolving standard for the next version of HTML after 4.01. HTML5 templates will work with dmBridge without any issues.

Collection access

In deciding which template set to load for a given URL, dmBridge parses the URL to determine whether a collection alias is present. If it is, it will load the template set that has been associated with that collection in the Template Sets section of the Control Panel. If it is not, it will use the template set that has been specified as the system-wide default.

Also in this section, it is possible to specify collections that are not allowed to appear in a given template set. This will prevent these collections from appearing in search forms, and it will prevent objects from these collections from appearing in search results.

Custom template sets

The dmBridge distribution includes two template sets. One, called "Clean White," is already styled. The other, called "Basic," is deliberately spartan, intended to be a starting point for your own creations, rather than a finished set of templates itself.

The dmBridge templates can be designed like any other HTML page using the text or WYSIWYG editor of your choice. The only extra consideration is styling the dynamically-generated content produced by the template helper methods. Obviously, you need to see the HTML code they produce in order to style it. One way to do this is by viewing the source of the generated page in your web browser. A better way is using a DOM inspection tool such as:

  • The Firebug extension for Firefox

  • The Developer Tools built into IE

  • The Web Inspector built into Safari

All of these will enable you to "zoom in" on a specific element in order to find CSS classes or IDs that your CSS rules can "grab onto," which makes writing them relatively easy.

The following is a walkthrough of the template customization process:

  1. In dm/templates, make a copy of the basic folder. Give it a descriptive alphanumeric name in all-lowercase (substitute underscores for spaces). Here, we'll call it newtpls.

  2. Register the new template set in the Control Panel, and assign one or more collections to it.

  3. Navigate to your dm folder in your web browser, appending the collection alias you wish to view to the URL like so:

    http://my_cdm_server/dm/objects/alias

    Your collection should come up, displaying results view. Click on a result and object view will load, and so on.

  4. Enter the newtpls/templates folder. Notice subfolders like object, error, favorite, etc. Take a look inside any one of them and notice one or more files with the .html.php extension. These are dmBridge template files. Open one up and notice that it's an HTML file, with some <?php ?> tags in it. Each one of these files corresponds to one of the main views in the dmBridge templates: object view, results view, favorites view, etc. It should be fairly clear just by looking at them which one is which; check the title tag inside them if you're not sure.

If you have inspected any of the template files, you may be wondering about the code within the <?php ?> tags. These are calls to methods in the PHP API. The PHP API enables access to all dmBridge functionality from within the templates.

Views

The template engine is based on the concept of views. In practice, all web-based digital repository systems offer several common views, interconnected by hyperlinks. These views, and the linkages between them, are what support convenient access to the information contained in the system. The dmBridge view architecture is illustrated in Figure 7.1, “The finding process in dmBridge”. The orange ellipses in this figure represent user intent, and the blue boxes represent concrete views.

Figure 7.1. The finding process in dmBridge

The finding process in dmBridge

An explanation of each view follows.

Error view

Error view is displayed automatically in place of any of the other views when there is an unrecoverable fatal error. Enabling debug mode in config.ini will display more information about the error.

Favorites view

Favorites view is a subset of results view that displays a user's favorites. Because it inherits from results view, it has the same display options (e.g. list, grid, tile). It adds checkboxes and a "Remove From Favorites" button.

The dmBridge favorites are stored in the same cookie as the default CONTENTdm® favorites, so changes made to the favorites in dmBridge will show up in the default CONTENTdm® templates, and vice versa.

Favorites view only displays those objects to which the user has access from the current template set. If two template sets (A and B) exist, and neither has access to any of the collections accessible by the other, neither will render any favorites that the other will. But the favorites are still present in the user's cookie at all times.

Object view

Object view is used in single-object context. Typically, it is accessed by clicking on a link from an object in results view. Object view supports both compound and non-compound objects. When using the HTML templates in this view, keep in mind that either view_simple.html.php or view_compound.html.php may be loaded depending on whether or not the object is compound.

Object-results view

Object-results view is used to display compound object search results. Results are displayed in a two-column HTML table, one object per row, with the page title in the left column and the full text of the page in the right column. Only pages that match the search query are displayed; matching terms are enclosed in an HTML <span> element with class dmHighlightedTerm. This view is only available for searchable compound objects.

Results view

Results view is used in contexts where a number of objects are displayed alongside each other. It can be populated by any group of objects, such as search results, browse results, or a user's favorites. (Favorites are handled by Favorites view, a subset of results view.)

There are two results view templates inside any template set folder: object/results.html.php and object/results_faceted.html.php. When dmBridge has facets to display, it will load the latter. The reason these are separate is because the presentation of facets often requires a major difference in HTML layout. If you find that this is not the case for you, feel free to remove all of the content from one of them and include() the other from it in order to eliminate redundancy.

Results view can be customized in the on a per-collection basis. See the Control Panel section for a list and description of the available options.

Results view provides several possible views within itself, each of which are just different ways of displaying objects. An easy way of rendering links to each of these views is using the DMResultsTemplateHelper::viewLinks() method. The user can always get any view by supplying the view parameter in the URI query string, e.g. ?view=tile. It is not currently possible to disable those views entirely.

Grid view

Grid view displays results in an HTML table, with one result per row. Columns are customizable and configurable in the Collections section of the Control Panel on a per-collection (not per-template-set) basis. Grid view is the default view within results view.

List view

List view is like an inverted grid view, with metadata fields displayed vertically per-object instead of horizontally. List view can be accessed within results view by supplying the ?view=list parameter in the URI.

Tile view

Tile view, like grid view, displays results in an HTML table. However, in tile view, each object has its own table cell. The number of columns is configurable in the Collections section of the Control Panel on a per-collection (not per-template set) basis. If you are using DMResultsTemplateHelper::getHtmlResults() to display results in your templates, which the built-in "Basic" template set does, tile view can be accessed within results view by supplying the ?view=tile parameter in the URI.

Search view

Search view is used to display the advanced search form(s) (not search results, which are handled by results view). This view is not strictly necessary for all digital collections - you could write your own search interface, or use Custom Queries and Results (CQR) - but is provided anyway due to the complexity of the forms.

As you may already know, CONTENTdm® provides four different search forms on its Advanced Search page, allowing the user to search "across all fields;" "selected fields;" "by proximity;" or "by date." dmBridge merges the first two of these forms together, offering a total of three different search forms, which can be added to the advanced search template (search/index.html.php) using the fieldSearch(), proximitySearch(), and dateSearch() methods of the DMSearchTemplateHelper class.

Login view

Login view is used to display a login form for authorized users to authenticate themselves. The login form is rendered by DMGenericTemplateHelper::getHtmlLoginForm() and is very simple, consisting of only two text fields and a submit button.

Like search view, login view is not strictly necessary for all digital collections. You could just as easily display the form on any other page, and never point users to login view at all.

By default, the authentication process uses CONTENTdm®'s authentication system. This can be changed; see Chapter 9, User authentication.

[Note]Note

There is no "logout view;" the process of logging out sends the user to results view.

URI routes

objects

Displays the default collection in results view in the default template set.

objects/favorites

Displays favorites view in the default template set.

objects/login

Displays login view in the default template set.

objects/logout

Logs the user out, and redirects to objects.

objects/search

Displays search view in the default template set.

objects/[alias]

Displays the collection with alias [alias] in the template set assigned to that collection.

objects/[alias]/favorites

Displays favorites view in the template set assigned to the collection with alias [alias].

objects/[alias]/login

Displays login view in the template set assigned to the collection with alias [alias].

objects/[alias]/logout

Logs the user out, then redirects to objects/[alias].

objects/[alias]/search

Displays search view in the template set assigned to the collection with alias [alias].

objects/[alias]/[pointer]

Displays object view in the template set assigned to the collection with alias [alias].

objects/[alias]/[pointer]/comments

Displays an Atom feed of comments for the object with pointer [pointer] in the collection with alias [alias]. (There is no HTML template associated with this route.)

objects/[alias]/[ptr]/search

Displays object results view in the template set assigned to the collection with alias [alias].

Content representations

A representation is defined by the W3C as "data that encodes information about resource state." The dmBridge template engine is capable of returning different different resource representations at the same URI, for most URIs.

The template engine supports Atom for some URIs in addition to HTML. Note that although this is the case, actual templates are not involved for any representation except HTML. Other representations are not customizable.

[Note]Note

dmBridge 1.x supported RSS 2.0 and a severely limited version of RDF/XML. These have been discontinued in version 2.

Name URI extension Media type Object view Object comments view Results view Object-results view Favorites view Search view
Atom 1.0 .atom application/atom+xml Yes Yes Yes Yes
HTML (none) text/html Yes Yes Yes Yes Yes

HTML is the default representation. To specify an alternate representation, append the URI extension to the end of the URI.

Feed metadata can be changed in the Feeds section of the Control Panel.

Using the PHP API in the templates

Digital collections websites perform a lot of common tasks: they display objects, render a paginated results list, etc. The DMGenericTemplateHelper class and its subclasses serve to make a lot of this common functionality as easy as possible to implement. For example, by leveraging DMResultsViewTemplateHelper::getHtmlPageLinks(), you can do what would ordinarily take several dozen lines of code in just one line. And if the way getHtmlPageLinks() works ever changes, all of your templates that call it will use the upgraded functionality automatically. (Keeping the same output HTML structure from version to version, so as not to break CSS rules, is a high priority.)

As the class diagram in the PHP API documentation depicts, DMGenericTemplateHelper has several subclasses, each one of which is meant to correspond to a particular view. The child classes are essentially all supersets of DMGenericTemplateHelper; they share all of its functionality, and add more of their own.

Chapter 8. Control Panel

The Control Panel is a central administration point for dmBridge. For the most part, it is a web-based front-end to the dm/data/config.xml file. It also enables point-and-click moderation of social data, among other things. It could be thought of as the dmBridge equivalent of the CONTENTdm® administration module. It supplements, but does not replace it.

[Note]Note

The Control Panel does not regularly receive testing in Internet Explorer and has been known to have issues in IE in the past. Whether this remains the case is unknown. If you have problems with the Control Panel in IE, please try another browser.

The Control Panel is accessible at the following URL:

http://my_cdm_server/dm/admin

By default, dmBridge uses the CONTENTdm® authentication system, so only users who are able to log into the CONTENTdm® administration module are able to log into the Control Panel. To change this, see Chapter 9, User authentication.

Basic Setup

This very simple section enables customization of the institution name. The institution name is output in Atom feeds, the HTTP API, and, potentially, other places.

Modules

This section displays the list of available modules alongside their status (enabled or disabled). It is also possible to enable and disable modules here. For more information about modules, see Chapter 13, Modules.

Comments

Configure

Enable

Commenting can be enabled or disabled on a global basis. When disabled, the comment form will not display in object view, and new comments will be rejected via the HTTP API. Existing comments will still be accessible via both the HTTP API and the object view comments section.

Moderation

When comment moderation is enabled, new comments will be placed in a moderation queue before appearing in public. See the section called “Moderate” for more information about comment moderation.

If there are currently any comments in the moderation queue, and moderation is changed from enabled to disabled, all currently unmoderated comments will be automatically approved.

Email notification of new comments

If enabled, an email message will be sent to the email address set in the "email notification address" field below whenever a new comment is received.

Email notification address

The email address to which comment notification emails will be sent whenever a new comment is received, if "email notification of new comments" is enabled. If disabled, this has no effect.

Moderate

Displays the list of comments in the moderation queue, from which they can be approved or rejected. Rejected comments get deleted. If comment moderation is disabled, this section will remain empty.

Search

Enables editing and deleting of already approved comments.

Statistics

Displays various statistics concerning comments. Only approved comments are included in the statistics.

Ratings

Configure

Enable

Rating can be enabled or disabled on a global basis. When disabled, the rating form will not display in object view, and new ratings will be rejected via the HTTP API. Existing ratings will still be accessible via both the HTTP API and the object view rating section.

Statistics

Displays various statistics concerning ratings.

Tags

Configure

Enable

Tagging can be enabled or disabled on a global basis. When disabled, the tag form will not display in object view, and new tags will be rejected via the HTTP API. Existing tags will still be accessible via both the HTTP API and the object view tags section.

Moderation

When tag moderation is enabled, new tags will be placed in a moderation queue before appearing in public. See the section called “Moderate” for more information about tag moderation.

If there are currently any tags in the moderation queue, and moderation is changed from enabled to disabled, all currently unmoderated tags will be automatically approved.

Moderate

Displays the list of tags in the moderation queue, from which they can be approved or rejected. Rejected tags get deleted. If tag moderation is disabled, this section will remain empty.

View All

Displays a list of all currently approved tags, grouped by count.

Statistics

Displays various statistics concerning tags. Only approved tags are approved in the statistics.

Collections

View All

In this section, a list of all collections is displayed. The first collection is the "Untitled Collection," which is an abstract collection whose settings are inherited by other collections by default. The "custom preferences" column shows the current configuration of custom preferences for each collection.

By clicking on "edit" next to a collection, the settings for that collection can be changed.

Editing a collection

Template set

Specifies the template set in which the collection is to appear when the collection alias appears in the URI params. For example, if the URI is:

http://my_cdm_server/dm/objects/[alias]

Then the collection with alias [alias] will appear in the template set specified here.

If the collection alias is not specified in the URI params, the Default Collection's template set will be used.

Viewer assignments

CONTENTdm®, and therefore dmBridge, can theoretically support any file type. Certain file types, such as images, will use one type of object viewer, whereas other file types, such as PDFs, will use another. In

Every file type has a unique media (MIME) type, which is a standard way of identifying it across platforms. In this section, these media types are mapped to dmBrige object viewers.

Fields

This section displays the list of fields that have been assigned for the collection in the CONTENTdm® administration module. The settings made here will apply to the appearance of these fields in results view. (Note that not all of these fields will appear in results view; see below.)

Grid & list views

This section specifies the fields that will be visible in grid view and list view within results view. It does not apply to tile view, where only the title will be displayed.

Facets

This section specifies the facet fields that will be displayed when facets are available for display.

Date search

This section specifies the starting and ending year that the date search pulldown menus will default to in the date search form in search view .

URL Redirection

In this section, reference URLs can be routed to either the dmBridge templates or the CONTENTdm® templates on a per-collection basis. In order for this to work, the replacement reference URL redirection script must be installed. For more information, see the section called “Reference URL redirection”.

Template Sets

Add

Name

Every template set must have a unique name. This will be used only to identify the template set and will not be visible publicly. If the template set is collection-specific, it may be helpful to name the template set similarly to the collection.

The "folder name," below, is a preview of the name of the folder that the template set must reside in, depending on its name.

See the section called “Template sets” for more information about custom template sets.

Allowed collections

The settings in this section apply when the URI params do not contain a collection alias, for example: http://my_cdm_server/dm/objects. In this case, the template set of the default collection will be displayed. When this is the case, this template set will, by default, display the collection that is set as its default here, and will be limited to accessing only those collections that are checked as "allowed" when searching or displaying favorites.

Results per page

Controls the maximum number of results that will appear on one page in results view. This can be overridden with the rpp URI query parameter, e.g. ?rpp=20.

Tile view columns

The settings in this section apply when the URI params do not contain a collection alias, for example: http://my_cdm_server/dm/objects, and when the current results view is tile view.

View All

In this section, a list of all template sets is displayed. By clicking on "edit" next to a template set, the settings for that template set can be changed; the options are the same as those for adding a template set.

Clicking on "delete" will un-register the template set from dmBridge, but will not delete it from disk.

Feeds

To be valid, all Atom feeds are required to contain certain pieces of metadata. This metadata can be customized in this section.

CQR

Provides a converter for CONTENTdm® "Custom Queries & Results" (CQR) URLs. Simply paste your CONTENTdm® CQR code in the upper box and click "Convert." This is a one-way conversion.

Chapter 9. User authentication

By default, dmBridge performs authentication using its built-in DMCdmAuthenticationService class, which authenticates against CONTENTdm®'s HTTP authentication component the same as the CONTENTdm® administration module.

It is also possible to tell dmBridge to use a different authentication service. The file dm/extensions/CustomAuthenticationService.php contains a skeleton of a class needed to do this. To authenticate against some other service, like an LDAP server (for example), simply complete the authenticate() method and set dmbridge.authentication_class to the name of this class in config.ini. (You are free to rename this class, but you must keep it in the dm/extensions folder and the class name must match the filename.)

Chapter 10. Commenting

Commenting allows users to post comments on objects. Comments can be submitted via the template engine (in object view) as well as via the HTTP API.

Commenting is enabled by default, but can be disabled on a global basis in the Comments section of the Control Panel. This will prevent receiving of comments via all means, but will not affect output of comments that have already been stored.

In the template engine, ratings can also be disabled on a per-template set basis by removing any calls to $view->getHelper()->getHtmlCommentsSection() from the templates.

A commenting section can be included within an object view template (object/single.html.php and object/compound.html.php) using the $view->getHelper()->getHtmlCommentsSection() method call. This method will handle all aspects of generating the comment form and list of comments. You are free to style these however you wish using CSS.

dmBridge will post status messages to the flash in response to certain types of user input to this form - for example, when validation has failed or when the comment has been successfully posted. Therefore, when including comments in the template, it is a good idea to also include a call to $view->getHelper()->getHtmlFormattedFlash() in a conspicuous place in the template as well, in order to provide feedback to the user as to what has just happened in response to their input.

Comments can also be accessed and posted via the HTTP API.

Chapter 11. Rating

The ratings feature allows users to rate objects on a configurable numeric scale.

Rating is enabled by default, but can be disabled on a global basis in the Control Panel. This will prevent receiving of ratings via both the template engine and the HTTP API, but will not affect output of ratings in either of these components. Ratings that have already been received will still appear.

In the template engine, ratings can also be disabled on a per-template set basis by removing any calls to $view->getHelper()->getHtmlRatingsSection() from the templates.

The ratings feature can be included within an object view template (object/single.html.php and object/compound.html.php) using the $view->getHelper()->getHtmlRatingsSection() method. This method will handle all aspects of generating the rating form.

Ratings can also be accessed and posted via the HTTP API.

Chapter 12. Tagging

Social tagging allows users to ascribe words or brief phrases ("tags") to objects to facilitate finding and gathering based on a flat (non-hierarchical) taxonomy.

Tagging is enabled by default, but can be disabled on a global basis in the Control Panel. This will prevent receiving of tags via both the template engine and the HTTP API, but will not affect output of tags in either of these components. Tags that have already been received and approved will still appear.

In the template engine, tagging can also be disabled on a per-template set basis by removing any calls to $view->getHelper()->getHtmlTaggingSection() from the templates.

The social tagging section can be included within an object view template (object/single.html.php and object/compound.html.php) using the $view->getHelper()->getHtmlTaggingSection() method. This method will handle all aspects of generating the tag input form. dmBridge will post status messages to the flash in response to certain types of user input to this form - for example, when validation has failed or when the tag has been successfully posted. Therefore, when including social tagging in the template, it is a good idea to also include a call to DMGenericTemplateHelper::getHtmlFormattedFlash() in a conspicuous place in the template as well, in order to provide feedback to the user as to what has just happened in response to their input.

Chapter 13. Modules

Installing modules

Modules are stored in self-contained subfolders within the dm/extensions/modules folder. Once in place here, they can be enabled and disabled via the Modules section of the Control Panel.

Upgrading modules

To upgrade a module, follow these steps:

  1. Check the module's documentation to ensure that it is compatible with your dmBridge version.

  2. In the Modules section of the Control Panel, disable the current module.

  3. Back up the old module folder and install the new one in its place.

  4. Optionally, if your module uses a database, back that up as well. Ensuring data integrity is the responsibility of the module's author.

  5. In the Modules section of the Control Panel, enable the new version of the module.

Chapter 14. Custom queries and results (CQR)

With minor changes, dmBridge is compatible with CQR generated by the CONTENTdm® CQR generator. The CQR generator returns code pointing to /cdm4/browse.php; this needs to be changed to /dm/objects to work with dmBridge.

Beginning with version 2.0, dmBridge includes a tool for converting CONTENTdm® CQR code to dmBridge format. This tool is accessible in the the section called “CQR” section of the Control Panel. This tool essentially automates what is explained below.

A custom query consists of the URL of a PHP script (/cdm4/results.php) followed by a series of "key-value pairs." Below is a custom query with key-value pairs split apart onto their own lines for readability:


/cdm4/results.php
?CISORESTMP=/cdm4/results.php
&CISOVIEWTMP=/cdm4/item_viewer.php
&CISOMODE=thumb
&CISOGRID=thumbnail,A,1;title,A,1;note,A,0...
&CISOBIB=title,A,1,N;note,A,0,N;creato,200...
&CISOTHUMB=20%20%284x5%29;title,none...
&CISOHIERA=20;creato,title,none,none,none
&CISOTYPE=link
&CISOOP1=exact
&CISOFIELD1=local
&CISOBOX1=vinas
&CISOOP2=exact
&CISOFIELD2=creato
&CISOBOX2=
&CISOOP3=exact
&CISOFIELD3=origin
&CISOBOX3=
&CISOOP4=exact
&CISOFIELD4=CISOSEARCHALL
&CISOBOX4=
&c=exact
&CISOROOT=/showgirls

There are quite a few key-value pairs here. dmBridge needs only the ones that begin with CISOOP, CISOFIELD, CISOBOX, and CISOROOT (which mean matching mode, field, search string, and collection alias, respectively). As far as dmBridge is concerned, it's safe to delete the rest, or keep them - it doesn't matter. The above CONTENTdm® CQR converted to dmBridge format would look like:

/dm/objects
&CISOOP1=exact
&CISOFIELD1=local
&CISOBOX1=vinas
&CISOROOT=/showgirls

As you can see, we have dropped anything not starting with CISOOP, CISOFIELD, CISOBOX, or CISOROOT. We have also dropped CISOOP 2 through 4, CISOFIELD 2 through 4, and CISOBOX 2 through 4, because they were empty. (If the CISOOP of a particular number is empty, it and the corresponding CISOFIELD and CISOBOX can be dropped.)

Chapter 15. Search suggestions

dmBridge is able to provide search suggestions from CONTENTdm® field indices based on user input from the HTTP query string. What this means is that you can do something like the following:

http://your_cdm_server/dm/api/search/suggest&CISOROOT=/uw&CISOFIELD1=title&CISOBOX1=building

And receive a list of suggestions for your term - in this case, "building." Whatever JavaScript solution you use for suggestions should query this URI. dmBridge tries to be client-code-agnostic, and to that end, it leaves the JavaScript up to you.

Search suggestions are a documented feature of the dmBridge HTTP API. More information about them is available by navigating to your HTTP API documentation, available at http://my_cdm_server/dm/api/1/doc.

Chapter 16. Term clouds

A "cloud" is a visual cluster of words or phrases based on some kind of vocabulary. This vocabulary may be the contents of one or more local metadata fields, or a user-submitted vocabulary ("folksonomy"). In dmBridge, there are two types of clouds: those based on social tags (tag clouds), and those based on field vocabulary (vocabulary clouds). These are considered to be distinct subsets of term clouds. Normally, terms in a cloud have some kind of visual distinction from each other (color and/or size) based on the frequency that they appear in the information corpus. On a web page, these distinctions are controlled by CSS properties like color, font-size, font-weight, etc.

dmBridge is able to generate term clouds based on Dublin Core field vocabulary (see DMGenericTemplateHelper::getHtmlVocabularyAsCloud()). Social tag clouds are output by DMGenericTemplateHelper::getHtmlTagsAsCloud(). Both classes output tags as HTML anchor (<a>) elements with no enclosing element. These elements receive a CSS class attribute of dmTagX, where X is an integer from 1 to 10. With social tags, all tags are output with the same class of dmTag.

Chapter 17. Sitemaps

dmBridge supports the Sitemaps standard, which is intended to help search engines index your content.

By default, your sitemap index is located at http://my_cdm_server/dm/sitemap. To inform search engines about its location, modify the "Sitemap" element in robots.txt, located at the root of your dmBridge folder. In order for this file to work, you will need to move it into your web server's document root, where search engine crawlers will be looking for it.

Chapter 18. Highlighted object

Highlighted object functionality is provided by the bundled UNLVHighlight module. The highlighted object can be returned via the dmBridge PHP and HTTP APIs.

To access it using the PHP API, call the static getHighlighted() method on DMObject. This will return an object of type DMObject. Example:

<?php
$obj = UNLVHighlightedObject::getHighlightedObject();
echo $obj->getField("title");
?>

To access the highlighted object using the HTTP API, navigate to http://my_cdm_server/dm/api/1/objects/highlighted.

Chapter 19. Random objects

Random object functionality is provided by the bundled UNLVRandom module. The random object can be returned using the PHP and HTTP APIs.

To access it using the PHP API, use the DMObject::getRandom() method, which returns an object of type DMObject:

<?php
$obj = UNLVRandomObject::getRandomObject();
echo $obj->getField("title");
?>

To access the random object using the HTTP API, navigate to http://my_cdm_server/dm/api/objects/random. JSON is available by appending .json to the URI. HTTP clients that request JSON as a preferred content type in their HTTP Accept header should receive it automatically.

Chapter 20. Spatial objects

CONTENTdm® does not have a provision for spatial browsing, searching, or visualization. Spatial boundary coordinates may be encoded in a qualified Dublin Core "Coverage-Spatial" field per commonly accepted best practice, but these are often encoded in different ways across sites, and often not machine-readable. Without being able to intuitively search or visualize it, the utility of this metadata cannot be realized.

This is where UNLVSpatial comes in. UNLVSpatial enables import, storage, browsing, searching, and cartographic visualization of spatial object metadata. It provides:

  • A section in the Control Panel for browsing object spatial metadata and importing metadata from existing DCMI Box- and DCMI Point-encoded spatial metadata in CONTENTdm®.

  • A set of custom template helpers for viewing the currently-viewed object in a map in object view; viewing the current result set in a map in results view; and visually searching by spatial boundary coordinates in search view.

  • Programmatic access to spatial object metadata via the PHP and HTTP APIs.

UNLVSpatial works especially well for cartographic materials, but it can work with any other kind of object that can be described geographically. It uses the Google Maps v3 API.

Importing spatial object metadata

Spatial metadata must reside in DCSV-encoded DCMI Box or DCMI Point format inside a "Coverage" element of an object's metadata record.

Because CONTENTdm® does not support querying of spatial data, UNLVSpatial requires that any spatial data for spatial searching be stored in the dmBridge data store. To get it there requires importing it, which is done in the "Spatial Objects" section of the Control Panel. Spatial metadata that is not to be used with spatial searching does not need to be imported, as it will be parsed out of the "Coverage" element on-the-fly.

Spatial metadata is associated with individual CONTENTdm® objects. The current version of UNLVSpatial supports both rectangular and point data. Polar-projection and other non-Cartesian maps are not supported. UNLVSpatial supports only decimal degree coordinates. One CONTENTdm® object supports one point or boundary rectangle.

Embedding maps in the templates

By default, UNLVSpatial is enabled in the Clean White template set. To enable it in other template sets, simply copy the relevant code from the Clean White templates. Refer to the section called “Custom template sets” for more information about template sets.

In the templates, UNLVSpatial works using three template helpers:

getHtmlGoogleMapsObject()

Renders a Google Map containing a point or rect representation of a single object, e.g. for object view. See the PHP API documentation or source code for optional method parameters.

getHtmlGoogleMapsObjectResults()

Renders a Google Map containing point or rect representations of multiple objects, e.g. for results view. See the PHP API documentation or source code for optional method parameters.

getHtmlGoogleMapsSpatialSearch()

Renders a search form containing a Google Map for spatial searching. Used in search view. See the PHP API documentation or source code for optional method parameters.

Before calling any of these methods, make sure to check whether the UNLVSpatial module is actually enabled, otherwise they will cause a fatal error. For example:

<?php if (DMModuleManager::getInstance()->isModuleEnabled("UNLVSpatial")): ?>
    <?php if (count($view->getHelper()->getSpatialObjects())): ?>
        <?php echo $view->getHelper()->getHtmlGoogleMapsObjectResults() ?>
    <?php endif ?>
<?php endif ?>

Spatial searching

By default, UNLVSpatial is enabled in the Clean White template set. The spatial search form appears in the section called “Search view”, consisting of a map with three radio buttons beneath it in addition to the standard collection checkboxes that appear in the other search forms. When the "Search" button is clicked, the system will search for maps based on the map viewport, and present the results in a custom results view. This is not the built-in the section called “Results view” -- notice the different URI -- even though it uses the standard results view template. Since it is not technically results view, certain features like Chapter 14, Custom queries and results (CQR) will not work with it. A spatial search is incompatible with a standard metadata search and both cannot be conducted simultaneously.

[Note]Note

Only objects whose spatial data has been imported will appear in the results.

Accessing spatial data programmatically

Via the HTTP API

Spatial data access via the HTTP API is read-only. When the UNLVSpatial module is enabled, its HTTP API documentation will appear in the dmBridge HTTP API documentation and will not be duplicated here.

Via the PHP API

Loading spatial data

The following example will retrieve an object's spatial data.

$col = DMCollectionFactory::getCollection("/sample");
$obj = DMObjectFactory::getObject($col, 5);
UNLVSpatialObjectFactory::spatializeObject($obj);

try {
    if ($obj->getSpatialModelClassName() == "UNLVSpatialRectObject") {
        echo $obj->getSpatialNorthLat();
        echo $obj->getSpatialSouthLat();
        echo $obj->getSpatialWestLong();
        echo $obj->getSpatialEastLong();
    } else { // it must be a point
        echo $obj->getSpatialLat();
        echo $obj->getSpatialLong();
    }
} catch (DMNoSuchMethodException $e) {
    echo "This object has no spatial metadata.";
}

Querying spatial data

Spatial data can be easily retrieved using a UNLVSpatialQuery. An example:

$example_obj = new UNLVSpatialRectObject();
$example_obj->setSpatialNorthLat(45.5);
$example_obj->setSpatialSouthLat(24.6);
$example_obj->setSpatialWestLong(-125);
$example_obj->setSpatialEastLong(-115);

$term = new UNLVSpatialQueryTerm();
$term->setExampleObject($example_obj);
$term->setMatchingMode("within");

$query = new UNLVSpatialQuery();
$query->addQueryTerm($term);

$results = $query->getSearchResults();
print_r($results);

UNLVSpatialQuery has additional methods for pagination, specifying search collections, and more. See the PHP API documentation for more information.

Adding and updating spatial data

The recommended way of adding spatial data is to instantiate a new UNLVSpatialObject; associate it with an existing DMObject; and persist it, as in the following example:

// Update a rectangle object
$collection = DMCollectionFactory::getCollection("/whatever");
$obj = DMObjectFactory::getObject($collection, 123);

$sp_obj = new UNLVSpatialRectObject();
$sp_obj->setSpatialNorthLat(45);
$sp_obj->setSpatialSouthLat(40);
$sp_obj->setSpatialWestlong(-115);
$sp_obj->setSpatialEastLong(-110);
$obj->addAssociatedModel($sp_obj);

UNLVSpatial::getDataStore()->updateObject($obj);


// Update a point object
$collection = DMCollectionFactory::getCollection("/whatever");
$obj = DMObjectFactory::getObject($collection, 456);

$sp_obj = new UNLVSpatialPointObject();
$sp_obj->setSpatialLat(45);
$sp_obj->setSpatialLong(-110);
$obj->addAssociatedModel($sp_obj);

UNLVSpatial::getDataStore()->updateObject($obj);

The call to updateObject() will insert the data if it does not already exist, and update it if it does.

Deleting spatial data

To delete spatial data, first we retrieve the DMObject whose spatial data we want to delete, then we "delete" it:

$collection = DMCollectionFactory::getCollection("/whatever");
$obj = DMObjectFactory::getObject($collection, 123);

UNLVSpatial::getDataStore()->deleteObject($obj);

The call to deleteObject() does not actually delete the given object -- only its spatial metadata.

Part IV. Developing with dmBridge

Chapter 21. PHP API

The dmBridge PHP API is a high-level, object-oriented API for CONTENTdm® that goes far beyond the CONTENTdm® PHP API. The dmBridge PHP API expedites development by making CONTENTdm® objects easy to work with:

<?php
$col = DMCollectionFactory::getCollection("/uw");
$obj = DMObjectFactory::getObject($col, 5);

echo $obj->getMetadata("title");
echo $obj->getThumbnailURL();

if ($obj->isCompound()) {
	echo "Page 1 is titled: " . $obj->getChild(0)->getTitle();
	echo "It's in this collection: "
		. $obj->getChild(0)->getCollection()->getName();
}
?>

The PHP API is not a separate component, and is not even a distinct architectural feature within the dmBridge code base. It is the code base, giving the developer access to the entire dmBridge PHP namespace, including all of the classes and functions it provides.

The PHP API is available automatically within the page templates. (The DMGenericTemplateHelper class and its subclasses are actually part of it, although they only work inside the templates.) It can also be included by other PHP scripts on the same server with code like the following:

<?php include_once("/path/to/dm/api.php"); ?>

The API documentation is included with the dmBridge distribution in the doc/php_api folder. The documentation provides a list of all methods that are publicly available in all classes. Most you will never have any reason to work with. But classes like DMObject, DMCollection, DMComment, etc. may offer some useful functionality if you need it.

As a template developer, the class you will work with the most in the templates is DMGenericTemplateHelper and its subclasses. For a list of methods available in these classes, consult the API documentation. Also, check out the sample templates for working examples of these methods in action.

When working with dmBridge code, you may find it helpful to use integrated development environment (IDE) software. This will provide features like a tabbed editor; syntax highlighting; file browser; class and method name autocompletion; and/or inline method documentation. Popular PHP IDEs include NetBeans, Eclipse, and Zend Studio. IDE choice can be quite personal and this is only a intended as a tip for those not already acquainted with PHP IDEs.

Chapter 22. Template helpers

Introduction

A template helper is a class that encapsulates one or more pieces of dynamic template code. Template helper classes can be provided by custom modules, or they can be written standalone. The purpose of a custom template helper is to add functionality to your page templates when the DMGenericTemplateHelper classes do not meet your needs.

[Note]Note

Custom helpers were known as "extensions" in dmBridge 1.x. They have been renamed because version 2 supports several other types of "extensions," of which custom helpers are only one kind.

Advantages of template helpers include:

  • They are isolated from the rest of the dmBridge code, making them easy to preserve across upgrades.

  • They are isolated from the rest of your template code, allowing them to be shared across template sets, and among other users.

  • They are consolidated and organized, making customizations easy to find.

  • They respect the standard dmBridge programming interfaces.

  • They prevent unexpected side effects from propagating to unexpected places.

  • They are unit-testable.

  • They hook into dmBridge's script and stylesheet management system, preventing duplicate scripts and stylesheets from being inserted into the page.

Using template helpers does not require PHP proficiency, but writing them does.

Writing template helpers

A template helper consists of one or more custom classes that you write yourself, each with one or more methods that you also write yourself. Custom template helper classes do not need to implement any interfaces, but they do need to extend DMCustomTemplateHelper. (Module template helpers work a little differently; see the section called “Using custom template helpers”.)

A simple template helper

A simple template helper looks like this:

<?php
class MyTemplateHelper extends DMCustomTemplateHelper {

    /**
     * Here, we are reimplementing the method we want to
     * override: in this case, the DMObjectTemplateHelper class'
     * getHtmlMetadataAsDL() method. We cannot literally override this method;
     * we must name it differently due to the way custom template helpers work.
     * And then we return the result:
     */
    public function getCustomHtmlMetadataAsDL() {
        // Assemble some HTML...
        $result = '<dl>
           <dt>Author</dt>
           <dd>Anonymous</dd>
        </dl>';

        // And then return it
        return $result;
    }

}
?>

This method will now be accessible from our page templates like so:

<?php echo $view->getHelper()->getCustomHtmlMetadataAsDL() ?>

The template helper concept contrasts with other strategies for adding dynamic functionality to dmBridge templates. For example, it would be easy to add blocks of PHP code directly in the template. This is not recommended due to its negation of most of the advantages outlined in the introduction to template helpers. It would also be possible to modify dmBridge code in-place. This is a bad idea for obvious reasons.

Template helper files must be saved in the dm/extensions/helpers folder, inside a folder named the same as their class name. (The path of the example above would be dm/extensions/helpers/MyTemplateHelper/MyTemplateHelper.php.) The class name doesn't matter, but it should briefly describe the purpose of the helper and be unique.

[Note]Note

The PHP engine is not able to load two classes with the same name simultaneously. Whenever dmBridge looks for a class, its class loader will look in the custom helpers folder last. Therefore, a custom helper whose name is the same as that of another dmBridge class will never get loaded.

Using custom stylesheets and JavaScripts

Template helpers may need to use a custom JavaScript from a script tag. They may want to provide some default styles. script tags (for JavaScripts) are allowed in the HTML body, but link (for stylesheets) is not. And even though script tags are allowed in the body, it may be difficult to avoid including a script that has already been included; for example, one template helper might want to include the jQuery library, and another may want to include it as well, leading to a clash.

This problem is solved by the following methods in the DMGenericTemplateHelper class:

  • addMetaTag()

  • addScriptTag()

  • addStylesheetTag()

All template helpers that require any functionality provided by a meta, script, or link tag will call these methods to add it, instead of outputting it in their markup. Then, in the appropriate places in the templates, the following methods are called:

  • getHtmlMetaTags()

  • getHtmlScriptTags()

  • getHtmlStylesheetTags()

An example follows:

<?php

/**
 * The template helper
 */
class MyTemplateHelper extends DMCustomTemplateHelper {

    public function helperWillRender() {
        $base_uri = DMConfigIni::getInstance()->getString(
           "dmbridge.base_uri_path");
        $this->addMetaTag("Bill", "author");
        $this->addHeadScriptTag("http://somewhere/jquery.js");
        $this->addBodyScriptTag(
           $base_uri . "/extensions/helpers/MyTemplateHelper/awesome.js");
        $this->addStylesheetTag(
           $base_uri . "/extensions/helpers/MyTemplateHelper/awesome.css");
    }

    public function getSomeAwesomeHtml() {
        return "<p>This is some awesome HTML!</p>";
    }

} ?>

<!-- The template -->
<html>
    <head>
        <?php echo $view->getHelper()->getHtmlMetaTags() ?>
        <?php echo $view->getHelper()->getHtmlStylesheetTags() ?>
        <?php echo $view->getHelper()->getHtmlHeadScriptTags() ?>
    </head>
    <body>
        <?php echo $view->getHelper()->getSomeAwesomeHtml() ?>
        <?php echo $view->getHelper()->getHtmlBodyScriptTags() ?>
    </body>
    </html>

In the MyTemplateHelper class, notice the helperWillRender() method. This is a delegate method called by the DMInternalView instance before the template has been rendered, and thus before any template helper methods have been called. This is necessary because if a helper were to be executed in the body -- as most are -- it would have no other way of inserting content in the head.

In the HTML template, Note that there are two separate methods called to insert scripts onto the page -- one in the head section (getHtmlHeadScriptTags()), and one in the body section (getHtmlBodyScriptTags()). Placing scripts in the body is a good general web design practice, as it helps pages to load faster; but it is not always possible. It is common to include e.g. framework scripts (such as jQuery or YUI) in the head section, and as many of the rest as possible in the body section.

Even though, for example, getHtmlMetaTags() outputs a series of meta tags, it is possible to write the directly in the template. The advantage of using this accessor mechanism is that it avoids placing duplicate tags on the page, and it makes it possible for template helpers to place their required tags in the right place.

Chapter 23. Object viewers

Object view would be of limited utility without the ability to actually view an object on the page. Object viewers enable this. CONTENTdm® is capable of storing any file type, and dmBridge should therefore ideally be able to display as many different file types (images, audio, text, video...) as possible.

Every object viewer in dmBridge is its own class, in its own file on disk. A number of object viewers are provided (in the dm/system/template/viewers folder) that are capable of handling many common file types.

Object viewers are assigned on a per-collection basis. Which viewer is used for which file type depends on the associations defined in the Collections section of the Control Panel. Here, you can associate a particular object viewer class with a particular media (MIME) type.

Every object viewer class must implement the DMObjectViewerDelegate interface. This requires writing three methods:

getName()

Should return the name of the viewer.

getHTMLTag()

Should return an HTML fragment that will render the viewer.

getHTMLTagNoJS()

Should return an HTML fragment that will render the viewer without any required or optional JavaScript. This should be written even if the viewer will not work without JavaScript; clients will assume the responsibility of including the necessary script(s) themselves.

isLowBandwidthCompatible() (new in 2.1)

Should return true or false depending on whether the content rendered by the object viewer is expected to always be "low-bandwidth safe." "Low bandwidth," in this case, is somewhat subjective; if a significant portion of the users of the viewer will be expected to experience bandwidth-related problems, then the viewer is not low-bandwidth-safe.

Examples of generally low-bandwidth-compatible viewers include:

  • Streaming media players

  • Image viewers that display reduced-size derivatives of larger source objects

Examples of generally non-low-bandwidth-compatible viewers, in contrast, include any that link directly to an object's bitstream.

If an object viewer requires JavaScript or CSS, it must additionally implement a fourth method, viewerWillRender().

See dm/system/template/viewers/DMGenericImageViewer/DMGenericImageViewer.php for an example of how an object viewer works.

Adding your own custom object viewer is as simple as writing your own class in the pattern of the existing ones and defining the associations in the Collections section of the Control Panel.

Custom viewers must be saved in the dm/extensions/viewers folder. The class name of the viewer must match the filename, and the class file must be saved in a folder with the same name as the class. For example:

dm/extensions/viewers/
    MyCustomViewer/
        MyCustomViewer.php
			

MyCustomViewer.php, then, would contain a class named MyCustomViewer.

Chapter 24. Modules

Modules are the most advanced customization method available in dmBridge. They enable the addition of complex new functionality as self-contained units of code.

To write a module, you will need a firm grounding in object-oriented PHP programming, including classes, interfaces, exception handling, class inheritance, accessors, instance methods, and static (class) methods. dmBridge is architected in a way that could be considered more-or-less "standard Java OO" -- at least to the extent that that can be achieved in PHP 5.2 -- and although your modules do not have to work like this, they will need to interface with the dmBridge PHP API, which does.

With a module, all of the following are possible without modifying any built-in dmBridge code:

  • Add new HTTP API URI routes

  • Add new template engine URI routes

  • Add new URI routes of any other kind

  • Add or override controllers that responds to any of these routes

  • Output your own HTTP content representations in any route

  • Write your own template helpers (if your module uses HTML templates)

  • Add sections to the Control Panel containing your own custom forms

  • Set up and query your own custom tables in the dmBridge data store

The process of writing a dmBridge module is fairly complex compared to authoring a template helper or custom viewer. However, the ability exists for developers who require it. As in any other reasonably complex object-oriented API, persistence pays off.

Module guidelines

  • Modules should be built to work in PHP 5.2.

  • Modules should use distinctive class, function, constant, and variable names as necessary in order to avoid naming clashes.

  • Modules should not require any PHP extensions beyond those required by dmBridge (this is suggested but not required).

  • The module's folder should contain all the code necessary to make the module work.

Module architecture

The simplest possible module is a single class that implements the root module interface, DMBridgeModule. This class (called, for example, SampleModule) resides in a file called SampleModule.php within the dm/extensions/modules/SampleModule folder. (SampleModule is a real module included in this location.)

A simple interface hierarchy exists to define "contracts" for modules that perform different functions, such as the ones in the list above. The root interface is DMBridgeModule, and all modules must implement it. Additionally, they may implement any combination of the following other interfaces if they so choose:

DMBridgeModule

The root module interface that all modules must implement. This serves to identify the module and access its basic information, including its name and version.

DMBridgeControlPanelModule

To be implemented by modules that intend to add their own sections in the Control Panel.

DMBridgeDataStoreModule

To be implemented by modules that intend to use their own tables in the dmBridge data store.

DMBridgeRepresentationSchemaModule

To be implemented by modules that intend to supply their own representation schema (normally an XML Schema) in the HTTP API.

DMBridgeTemplateHelperModule

To be implemented by modules that provide their own template helpers.

The name of the main module class is not important, but it should be distinctive in order to avoid class name clashes.

Environment bootstrapping

A module needs to initialize its own environment. The folder structure of a module is essentially free-form, so dmBridge itself isn't going to know all of the different bits and pieces that the module is going to need to include(). The bootstrap.php file needs to contain at least enough code to enable dmBridge to instantiate the module's main class. That means it needs to either include the main class directly, or via its own custom autoloader.

The bootstrap.php file need not include all of the module's files at once. In fact, this would be a bad idea for performance reasons. It is perfectly acceptable to use an autoloader, or to have individual class files include only their own collaborators via include_once() or require_once().

Exposing URI routes

If a module is to expose its own URI routes, it needs a way to tell dmBridge what URI routes those are. A "route" is the portion of the URI that dmBridge uses to figure out what to do. For example, in the following URI:

http://my_cdm_server/dm/objects/uw/52

The route is objects/uw/52. When dmBridge sees a URI matching this pattern, its own built-in routes.xml file tells it to invoke DMTEObjectController::view(), passing in an ID of 52 as a method parameter. (Take a look at dm/includes/routes.xml to see how this works. A module's routes.xml file should be structured the same way.)

Every route in a module's routes.xml file needs to be mapped to a class instance method. The class in question is typically a custom controller class provided by the module.

When the dmBridge system searches for a route, it will look for module-provided routes first. Still, modules should strongly avoid overriding built-in routes.

Controllers

The controller in dmBridge is the point of entry into the execution of the application. The job of the controller is to coordinate various application layers to produce a given result based on user input. Different controllers are invoked depending on the current URI route. (See Figure 2.2, “Example of results view in the dmBridge MVC architecture” for an illustration of Model-View-Controller.)

Just as it is not possible to override built-in URI routes, it is not possible to override built-in controllers. However, custom controllers can be created that will respond to custom routes. Once a new URI route is established, dmBridge will attempt to invoke the controller method it specifies when a request is received for a URI matching that route. Custom controller classes should inherit from DMAbstractController, except for Control Panel controllers, which should inherit from DMCPAdminController. Control Panel controller methods should also call $this->preFlightCheck() before doing anything else.

Adding HTTP API documentation

If the module will be exposing new HTTP API methods, it should document them within a <HTTPAPIDocumentation> XML element. This documentation will be injected into the rest of the HTTP API documentation, available at http://my_cdm_server/dm/api/1/doc. See the http_api_doc.xml file in the UNLVHighlight module for an example of how this documentation is constructed.

Adding sections to the Control Panel

To add sections to the Control Panel, a module must implement the DMBridgeControlPanelModule interface. This involves writing a method called getControlPanelMenuSections(), which should return an array of DMCPMenuSection objects, to which one or more DMCPMenuItem objects have been added. The DMCPMenuItem objects should link to valid routes provided by the module.

See the bundled modules for an example of using templates and forms in the Control Panel.

Using custom template helpers

Modules that provide template helpers must implement the DMBridgeTemplateHelperModule interface, which defines a single method, getTemplateHelper(). Your getTemplateHelper() method should return an instance of your custom template helper class, which itself should implement DMTemplateHelper.

When calling module template helpers, be aware that the module with which they work may be unavailable from time to time, for whatever reason. It is therefore important to call them safely, by first checking to make sure the module is enabled:

<?php if (DMModuleManager::getInstance()->isModuleEnabled("MyModule")): ?>
    <?php echo $view->getHelper()->doSomething() ?>
<?php endif ?>

Using models

As far as a dmBridge module is concerned, there are two types of models: those that are native to dmBridge and those that are not. dmBridge-native models include DMObject, DMCollection, DMComment, etc., all of which inherit from DMModel. Non-native models could be any other class, including ones that the module defines itself.

[Caution]Caution

You should avoid subclassing dmBridge models to add new functionality. Doing so introduces unpredictable divergences in the class hierarchy which, with multiple interdependent modules active simultaneously, is likely to cause serious problems.

Using a custom model is simple: write it, save it to your module folder, and use it. Using a dmBridge model is similarly easy. However, there are instances where your module will need to add new functionality to existing dmBridge model classes, so that a dmBridge module will respond to its own methods, plus custom methods you've defined. The recommended method of achieving this is as follows:

  1. Define your own model class that consists of only the functionality (i.e. methods) you would like to add to a given dmBridge model class.

  2. Given an instance of your model class, $mymodel; and a dmBridge model instance, $dmmodel; associate your custom instance with the dmBridge instance by calling $dmmodel->addAssociatedModel($mymodel).

Now, with the $dmmodel instance having been "associated" with your own custom instance, it will respond to all of the methods that $mymodel would, using built-in PHP "magic."

[Caution]Caution

Try to give your custom model methods distinctive names, otherwise they could clash with those from other modules.

Persistence

[Note]Note

As of version 2.1, dmBridge's persistence mechanism is primitive and likely to change in a future version.

Localization

String localization can be achieved using the DMLocalizedString class. The getString() method accepts an optional $strings_folder parameter which can point to any folder containing string files. (If absent, only built-in strings will be available.) String files should be named strings.code.txt where "code" is an ISO 639-1 language code.

String files are simple UTF-8 text files in "Java properties file" format, consisting of one key-value pair per line.

KEY = value
KEY = value
KEY = value

Keys should be shared across strings files, but values, of course, should be localized appropriately in different files.

The current language is set in the dmbridge.language property in the config.ini file. Modules should always provide at least an English strings file, called strings.en.txt. This will be used as a fallback in case the user's requested dmbridge.language is not provided by your module.

Chapter 25. HTTP API

The dmBridge HTTP API is a multi-format (XML/JSON), versioned API that respects REST principles. The URI space is based on a general digital collections domain model. It is mostly read-only, except for social data. The HTTP API is available at the following URI:

http://my_cdm_server/dm/api/1

The XML and JSON APIs return the same data, respond to the same request URIs, and send the same HTTP response codes. The only difference is the data format.

The HTTP API attempts to return a content representation based on the preference ("Q value") supplied by the client in the HTTP Accept header. A representation can be forced by appending the appropriate file extension to the URI (.xml, .json, or .jsonp). If no extension is supplied, the Accept header will be consulted, and in the absence of a successful content negotiation, the behavior is undefined. Therefore, clients should make sure to specify a representation preference somehow.

Full method-level HTTP API documentation is included with the dmBridge software and is accessible via web browser at http://my_cdm_server/dm/api/1.

Present in the output of every HTTP API method is a copyright statement protecting the information being downloaded. This allows for widespread use of your content while asserting your legal rights. The copyright statement can be changed in the Feeds section of the Control Panel.