What’s new in Omeka 2.0
Principles of Omeka 2.0
People who are familiar with conventions and patterns from Omeka 1.x will see many changes. Here are some ofbroad principles that went into the changes to Omeka 2.0
Record-independent Functionality
The design of Omeka 1.x tended to treat different database records as superficially very different, despite the fact they all inherit from the same class. Thus, we had functions item()
alongside collection()
, both of which performed very similar jobs of retrieving data from a record. Similarly, we had loop_items()
and loop_collections()
. That pattern extended into our plugins, e.g. simple_page()
and loop_simple_pages()
. This created excessive duplication of functionality.
In Omeka 2.0, we instead concentrated on the similarity across all records, designing single functions for similar tasks that work by either passing in a record or by passing in the name of the record type current in a view. For example, to retrieve the id from the current item in a view, use metadata('item', 'id')
. For a collection: metadata('collection', 'id')
.
This requires some attention to the names of your models and how they are assigned to the view. The first parameter to metadata()
will be made singular, with the assumption that the view object has a record assigned to that property name. Similarly, looping assumes a plural form, an sets the current record to the singular name.
New Function Conventions
To make our function names more consistent and easier to understand, we have introduced the following conventions:
Functions that return an array or object begin with
get_
Functions that return a boolean begin with
is_
orhas_
Functions do not echo a string, instead they return the string
New Class Naming Conventions
In anticipation of an eventual move to using Zend Framework 2, we have reorganized our directories and class names to conform with those conventions. Abstract classes and interfaces now reflect that status in their names, and class names are generally laid out to read more naturally.
Also, the classes representing records and the table for them are no longer in the same directory. Instead, there is a Table
directory inside the directory containing the models. The name of the table class should be the model’s class name prefixed with Table_
, e.g. Table_SimplePagesPage
.
Migrating your code
There are significant changes moving from Omeka 1.5 to Omeka 2.0.
Here, you will find a skeleton of typical tasks that will be required to migrate your code. Consult the reference section for code details.
Omeka an Archive?
While archivists can (and many do) use Omeka as a presentation layer to their digital holdings, Omeka is not archival management software. To underscore this fact, we’ve removed all mention of the word “archive” in the Omeka codebase and filesystem. This will require at least two additional steps when upgrading from earlier versions to 2.0:
Rename the archive/files/ directory to /archive/original/:
$ mv /path/to/omeka/archive/files/ /path/to/omeka/archive/original/
Rename the archive/ directory to files/:
$ mv /path/to/omeka/archive/ /path/to/omeka/files/
Logging and Debugging
Developers of both themes and plugins will need to be aware of the following changes in Omeka’s .htaccess
file and config.ini
file in application/config
. Compare your existing files to the new .htaccess.changeme
and config.ini.changeme
files
.htaccess
now includes an environment variable for development:# SetEnv APPLICATION_ENV development
config.ini
now includes a setting for the minimal level of error logging. The default level is WARN. DEBUG is the lowest level of priority, and will show all messages. _log — Log a message. allows you to set your a priority, and the setting inconfig.ini
must be set appropriately for the messages to be saved.; log.priority ; The minimum priority level of messages that should be logged. ; default: Zend_Log::WARN (Logs warnings and above) log.priority = Zend_Log::DEBUG
Note
debug — Log a message with ‘DEBUG’ priority. uses DEBUG priority, so to see messages logged by that function you must set the log priorty to DEBUG in
config.ini
.
Upgrading Plugins
As you look through the lists of typical tasks below, you might also want to consult Best Practices for Plugin Development
Typical tasks you will need to do to upgrade your plugins for Omeka 2.0 are:
Change the classes your controllers and models extend from.
Omeka_Controller_Action becomes
Omeka_Controller_AbstractActionController
Omeka_Record becomes
Omeka_Record_AbstractRecord
Update any helper functions you use in hooks for filters.
Change your hook callbacks to have an array passed in. Typically, the expected variable name passed in in version 1.5 (e.g.
$user
) becomes the key for the corresponding data in the array, e.g.$user = $args['user'];
. See Updating Plugins for 2.0: Hooks and FiltersUpdate any filters you use. The third argument must now be an array to fit with the standard above.
Change the helper functions used in the views * All functions of the form
loop_{record type}
, likeloop_items()
, becomeloop("{record type}")
Change usage of functions that previously echoed content. For example,
<?php head(); ?>
should now be<?php echo head(); ?>
.
Database
Record classes
The abstract class records extend from is now
Omeka_Record_AbstractRecord
, notOmeka_Record
The following callbacks have been removed, along with their associated plugin hooks:
beforeSaveForm
afterSaveForm
beforeInsert
afterInsert
beforeUpdate
afterUpdate
beforeValidate
afterValidate
Any logic currently in the
SaveForm
,Insert
, orUpdare
callbacks should be moved tobeforeSave
orafterSave
. Anything using the associated hooks should be moved to before_save_<model> or after_save_<model>. TheValidate
callbacks should be replaced by code in_validate
.A boolean insert argument for the
beforeSave
andafterSave
callbacks and hooks replaces the insert and update-specific versions.The
saveForm
andforceSave
methods are removed. UseOmeka_Record_AbstractRecord::save
instead.
Table classes
SQL aliases are no longer the initials of the underlying table, they are the full table name (without the prefix). For example, the Items table alias was
i
in Omeka 1.x, but it is nowitems
. You can callOmeka_Db_Table::getTableAlias
to get the alias.Table classes can now optionally use the naming pattern
Table_{Record}
instead of{Record}Table
. Omeka’s built-in tables use this new naming scheme.
Built-in records
The
Entity
,EntitiesRelations
, andEntityRelationships
models, and their underlying tables are removed. Any code relying on them must be changed or removed.User
now directly stores the name and email data for users that was previously in theEntity
.The separate first, middle, and last name fields for Users are combined into a single name field.
Built-in mixins
All mixins now have a prefix of
Mixin_
on their class name, and have a new naming convention:Ownable
is nowMixin_Owner
.Taggable
is nowMixin_Tag
.ActsAsElementText
is nowMixin_ElementText
.PublicFeatured
is nowMixin_PublicFeatured
.
ACL and Permissions
Omeka_Acl
is removed. All references toOmeka_Acl
should be toZend_Acl
instead.loadRoleList
,loadResourceList
, andloadAllowList
were Omeka-specific methods, and are now gone. Now, just directly make individual calls toaddRole()
,addResource()
, andallow()
. You no longer need to useloadResourceList()
to define the privileges for each resource.checkUserPermission
is also gone. UseisAllowed
instead:$acl->isAllowed(current_user(), 'Resource', 'privilege');
The
has_permission
global function is replaced byis_allowed
.
Controllers
Many methods that were previously directly called on a Controller are now controller helpers instead.
The database wrapper methods
findById()
,getTable('TableName')
,getDb()
are removed in favor of the Db helper:// old: $record = $this->findById(); $record = $this->_helper->db->findById(); // old: $element = $this->getTable('Element')->find($elementId); $element = $this->_helper->db->getTable('Element')->find($elementId); // old: $db = $this->getDb(); $db = $this->_helper->db->getDb();
The Db helper is also now used to set the default model name. The
_modelClass
property is removed in favor ofsetDefaultModelName
from the Db helper:// 1.x public function init() { $this->_modelClass = 'MyModel'; } // 2.0 public function init() { $this->_helper->db->setDefaultModelName('MyModel'); }
The
flash
,flashSuccess
, andflashError
methods are removed in favor of the FlashMessenger helper:$this->_helper->flashMessenger('A neutral message'); $this->_helper->flashMessenger('A success message!', 'success'); $this->_helper->flashMessenger('An error message.', 'error');
Omeka_Context
Omeka_Context
is removed. Resources are instead available directly throughZend_Registry
or through the bootstrap object:$acl = Zend_Registry::get('bootstrap')->getResource('Acl');
Views
Admin Views
Many new CSS classes are available and should be used to ensure a consistent look and feel across Omeka plugins. It will be helpful to become familiar with them. For example, this is the new code structure to use if you need to create inputs yourself:
<div class="field"> <div class="two columns alpha"> <label for="some_input" class="required">Some Input Label</label> </div> <div class="inputs five columns omega"> <input type="text" name="some_input"> </div> </div>
Admin theme now displays an
<h1>
with the title you set for the page. You can remove those from your admin views.Use new save panel features. For ease of use in the most common cases, the
Omeka_Form_Admin
is available.
Updating Themes
The number of global functions has been cut nearly in half in Omeka 2.0. This will require many changes to your themes, but will also make the patterns of usage much easier to follow and much more consistent.
Here are a few of the basic tasks for upgrading.
Change the various metadata-retrieval functions for different record types (e.g.,
item()
,collection()
, etc) to the generalized metadata — Get metadata for a record. function.Change the loop structure for the various record types (e.g.,
loop_items()
,loop_collections
, etc) to the generalized loop — Get an iterator for looping over an array of records. function. Note that the structure changes from:while(loop_items()):
to:
foreach(loop('items') as $item):
Use
get_records
when getting sets of any record within a theme.get_items
,get_tags
, andget_collections
are all replaced byget_records
.Change the structure of any arrays passed to nav — Create a navigation menu of links..
nav
now uses the Zend_Navigation component, which changes the way you need to specify the array of nav links. Zend has some more expansive documentation on the available options, but it’s pretty simple to convert the oldlabel => url
pairs to the new style:echo nav(array( array('label' => 'Browse All', 'uri' => url('items')) array('label' => 'Browse By Tag', 'uri' => url('items/tags')) ));
Update calls to hooks and filters (wherever you use fire_plugin_hook — Declare the point of execution for a specific plugin hook. and apply_filters — Apply a set of plugin filters to a given value.). Typically, the expected variable name passed in in version 1.5 (e.g.
$user
) becomes the key for the corresponding data in the array, e.g.$user = $args['user'];
See Updating Plugins for 2.0: Hooks and Filters
Changed Function Names
Old Function |
New Function |
---|---|
random_featured_item() |
random_featured_items(1) |
has_tags() |
metadata($record, 'has tags') |
item_has_tags() |
metadata($item, 'has tags') |
item_has_files() |
metadata($item, 'has files') |
item_has_thumbnail() |
metadata($item, 'has thumbnail') |
item_citation() |
metadata($item, 'citation') |
n/a |
metadata($item, 'file count') |
item_fullsize() |
item_image('fullsize') |
item_thumbnail() |
item_image('thumbnail') |
item_square_thumbnail() |
item_image('square_thumbnail') |
setting() |
option() |
display_js() |
head_js() |
display_css() |
head_css() |
css() |
css_src() |
js() |
js_tag() |
queue_js() |
queue_js_file() |
queue_css() |
queue_css_file() |
display_random_featured_collection() |
random_featured_collection() |
recent_collections() |
get_recent_collections() |
random_featured_collection() |
get_random_featured_collection() |
get_latest_omeka_version() |
latest_omeka_version() |
display_file() |
file_markup() |
display_files() |
file_markup() |
recent_files() |
get_recent_files() |
show_file_metadata() |
all_element_texts() |
_tag_attributes() |
tag_attributes() |
simple_search() |
simple_search_form() |
display_form_input_for_element() |
element_form() |
display_element_set_form() |
element_set_form() |
label_options() |
label_table_options() |
display_search_filters() |
search_filters() |
current_action_contexts() |
get_current_action_contexts() |
__v() |
get_view() |
display_files_for_item() |
files_for_item() |
display_random_featured_item() |
random_featured_item() |
display_random_featured_items() |
random_featured_items() |
recent_items() |
get_recent_items() |
random_featured_items() |
get_random_featured_items() |
random_featured_item() |
get_random_featured_item() |
show_item_metadata() |
all_element_texts() |
link_to_advanced_search() |
link_to_item_search() |
link_to_file_metadata() |
link_to_file_show() |
link_to_next_item() |
link_to_next_item_show() |
link_to_previous_item() |
link_to_previous_item_show() |
link_to_browse_items() |
link_to_items_browse() |
nls2p() |
text_to_paragraphs() |
recent_tags() |
get_recent_tags() |
item_tags_as_string() |
tag_string('item') |
item_tags_as_cloud() |
tag_cloud('item') |
has_permission() |
is_allowed() |
uri() |
url() |
abs_uri() |
absolute_url() |
abs_item_uri() |
record_url($item, 'show', true) |
record_uri() |
record_url() |
item_uri() |
record_url($item) |
current_uri() |
current_url() |
is_current_uri() |
is_current_url() |
items_output_uri() |
items_output_url() |
file_display_uri() |
file_display_url() |
public_uri() |
public_url() |
admin_uri() |
admin_url() |
set_theme_base_uri() |
set_theme_base_url() |
revert_theme_base_uri() |
revert_theme_base_url |
loop_records() |
loop() |
loop_files() |
loop('files') |
loop_collections() |
loop('collections') |
loop_items() |
loop('items') |
loop_item_types() |
loop('item_types') |
loop_items_in_collection() |
loop('items') |
loop_files_for_item() |
loop('files') |
set_current_file() |
set_current_record('file', $file) |
set_current_collection() |
set_current_record('collection', $collection) |
set_current_item() |
set_current_record('item', $item) |
get_current_item() |
get_current_record('item') |
get_current_collection() |
get_current_record('collection') |
get_current_file() |
get_current_record('file') |
get_current_item_type() |
get_current_record('item_type') |
set_current_item_type() |
set_current_record('item_type') |
set_items_for_loop() |
set_loop_records('items', $items) |
get_items_for_loop() |
get_loop_records('items') |
has_items_for_loop() |
has_loop_records('items') |
set_collections_for_loop() |
set_loop_records('collections', $items) |
get_collections_for_loop() |
get_loop_records('collections') |
has_collections_for_loop() |
has_loop_records('collections') |
set_files_for_loop() |
set_loop_records('files', $items) |
get_files_for_loop() |
get_loop_records('files') |
has_files_for_loop() |
has_loop_records('files') |
set_item_types_for_loop() |
set_loop_records('item_types', $itemTypes) |
get_item_types_for_loop() |
get_loop_records('item_types') |
has_item_types_for_loop() |
has_loop_records('item_types') |
get_item_by_id() |
get_record_by_id('item', $id) |
get_collection_by_id() |
get_record_by_id('collection', $id) |
get_user_by_id() |
get_record_by_id('user', $id) |
_select_from_table() |
get_table_options() with Zend's formSelect() |
is_odd($num) |
n/a; use $num & 1 |
form_error() |
n/a; Use Zend Form Validations |
collection_is_featured |
metadata('collection', 'featured') |
collection_is_public |
metadata('collection', 'public') |
button_to |
n/a; use Zend's form helpers or hand-write HTML buttons. |
delete_button |
link_to($record, 'delete-confirm', 'Delete', ...) |