PageRenderTime 137ms CodeModel.GetById 89ms app.highlight 38ms RepoModel.GetById 1ms app.codeStats 1ms

/app/models/ca_object_representations.php

https://bitbucket.org/Sinfin/pawtucket
PHP | 1170 lines | 790 code | 155 blank | 225 comment | 145 complexity | 29a39322a99433fd5c1a46dc74116dbe MD5 | raw file
   1<?php
   2/** ---------------------------------------------------------------------
   3 * app/models/ca_object_representations.php : table access class for table ca_object_representations
   4 * ----------------------------------------------------------------------
   5 * CollectiveAccess
   6 * Open-source collections management software
   7 * ----------------------------------------------------------------------
   8 *
   9 * Software by Whirl-i-Gig (http://www.whirl-i-gig.com)
  10 * Copyright 2008-2011 Whirl-i-Gig
  11 *
  12 * For more information visit http://www.CollectiveAccess.org
  13 *
  14 * This program is free software; you may redistribute it and/or modify it under
  15 * the terms of the provided license as published by Whirl-i-Gig
  16 *
  17 * CollectiveAccess is distributed in the hope that it will be useful, but
  18 * WITHOUT ANY WARRANTIES whatsoever, including any implied warranty of 
  19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  
  20 *
  21 * This source code is free and modifiable under the terms of 
  22 * GNU General Public License. (http://www.gnu.org/copyleft/gpl.html). See
  23 * the "license.txt" file for details, or visit the CollectiveAccess web site at
  24 * http://www.CollectiveAccess.org
  25 * 
  26 * @package CollectiveAccess
  27 * @subpackage models
  28 * @license http://www.gnu.org/copyleft/gpl.html GNU Public License version 3
  29 * 
  30 * ----------------------------------------------------------------------
  31 */
  32 
  33 /**
  34   *
  35   */
  36require_once(__CA_LIB_DIR__."/ca/IBundleProvider.php");
  37require_once(__CA_LIB_DIR__."/ca/BundlableLabelableBaseModelWithAttributes.php");
  38require_once(__CA_MODELS_DIR__."/ca_object_representation_labels.php");
  39require_once(__CA_MODELS_DIR__."/ca_representation_annotations.php");
  40require_once(__CA_MODELS_DIR__."/ca_representation_annotation_labels.php");
  41require_once(__CA_MODELS_DIR__."/ca_object_representation_multifiles.php");
  42
  43
  44BaseModel::$s_ca_models_definitions['ca_object_representations'] = array(
  45 	'NAME_SINGULAR' 	=> _t('object representation'),
  46 	'NAME_PLURAL' 		=> _t('object representations'),
  47 	'FIELDS' 			=> array(
  48 		'representation_id' => array(
  49				'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_HIDDEN, 
  50				'IDENTITY' => true, 'DISPLAY_WIDTH' => 10, 'DISPLAY_HEIGHT' => 1,
  51				'IS_NULL' => false, 
  52				'DEFAULT' => '',
  53				'LABEL' => 'Representation id', 'DESCRIPTION' => 'Identifier for Representation'
  54		),
  55		'locale_id' => array(
  56				'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_SELECT, 
  57				'DISPLAY_WIDTH' => 40, 'DISPLAY_HEIGHT' => 1,
  58				'IS_NULL' => true, 
  59				'DEFAULT' => '',
  60				'DISPLAY_FIELD' => array('ca_locales.name'),
  61				'LABEL' => _t('Locale'), 'DESCRIPTION' => _t('The locale from which the representation originates.')
  62		),
  63		'type_id' => array(
  64				'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_SELECT, 
  65				'DISPLAY_WIDTH' => 40, 'DISPLAY_HEIGHT' => 1,
  66				'DISPLAY_FIELD' => array('ca_list_items.item_value'),
  67				'DISPLAY_ORDERBY' => array('ca_list_items.item_value'),
  68				'IS_NULL' => false, 
  69				'LIST_CODE' => 'object_representation_types',
  70				'DEFAULT' => '',
  71				'LABEL' => _t('Type'), 'DESCRIPTION' => _t('Indicates the type of the representation. The type can only be set when creating a new representation and cannot be changed once the representation is saved.')
  72		),
  73		'idno' => array(
  74				'FIELD_TYPE' => FT_TEXT, 'DISPLAY_TYPE' => DT_FIELD, 
  75				'DISPLAY_WIDTH' => 40, 'DISPLAY_HEIGHT' => 1,
  76				'IS_NULL' => false, 
  77				'DEFAULT' => '',
  78				'LABEL' => _t('Representation identifier'), 'DESCRIPTION' => _t('A unique alphanumeric identifier for this representation.'),
  79				'BOUNDS_LENGTH' => array(0,255)
  80		),
  81		'idno_sort' => array(
  82				'FIELD_TYPE' => FT_TEXT, 'DISPLAY_TYPE' => DT_OMIT, 
  83				'DISPLAY_WIDTH' => 40, 'DISPLAY_HEIGHT' => 1,
  84				'IS_NULL' => false, 
  85				'DEFAULT' => '',
  86				'LABEL' => 'Sortable representation identifier', 'DESCRIPTION' => 'Value used for sorting representations on identifier value.',
  87				'BOUNDS_LENGTH' => array(0,255)
  88		),
  89		'media' => array(
  90				'FIELD_TYPE' => FT_MEDIA, 'DISPLAY_TYPE' => DT_FIELD, 
  91				'DISPLAY_WIDTH' => 88, 'DISPLAY_HEIGHT' => 15,
  92				'IS_NULL' => false, 
  93				'DEFAULT' => '',
  94				
  95				"MEDIA_PROCESSING_SETTING" => 'ca_object_representations',
  96				
  97				'LABEL' => _t('Media to upload'), 'DESCRIPTION' => _t('Use this control to select media from your computer to upload.')
  98		),
  99		'media_metadata' => array(
 100				'FIELD_TYPE' => FT_TEXT, 'DISPLAY_TYPE' => DT_OMIT, 
 101				'DISPLAY_WIDTH' => 88, 'DISPLAY_HEIGHT' => 15,
 102				'IS_NULL' => false, 
 103				'DEFAULT' => '',
 104				'LABEL' => _t('Media metadata'), 'DESCRIPTION' => _t('Media metadata')
 105		),
 106		'media_content' => array(
 107				'FIELD_TYPE' => FT_TEXT, 'DISPLAY_TYPE' => DT_OMIT, 
 108				'DISPLAY_WIDTH' => 88, 'DISPLAY_HEIGHT' => 15,
 109				'IS_NULL' => false, 
 110				'DEFAULT' => '',
 111				'LABEL' => _t('Media content'), 'DESCRIPTION' => _t('Media content')
 112		),
 113		'md5' => array(
 114				'FIELD_TYPE' => FT_TEXT, 'DISPLAY_TYPE' => DT_FIELD, 
 115				'DISPLAY_WIDTH' => 40, 'DISPLAY_HEIGHT' => 1,
 116				'IS_NULL' => false, 
 117				'DEFAULT' => '',
 118				'LABEL' => _t('MD5 hash'), 'DESCRIPTION' => _t('MD5-generated "fingerprint" for this media.'),
 119				'BOUNDS_LENGTH' => array(0,32)
 120		),
 121		'original_filename' => array(
 122				'FIELD_TYPE' => FT_TEXT, 'DISPLAY_TYPE' => DT_FIELD, 
 123				'DISPLAY_WIDTH' => 90, 'DISPLAY_HEIGHT' => 1,
 124				'IS_NULL' => false, 
 125				'DEFAULT' => '',
 126				'LABEL' => _t('Original filename'), 'DESCRIPTION' => _t('The filename of the media at the time of upload.'),
 127				'BOUNDS_LENGTH' => array(0,1024)
 128		),
 129		'access' => array(
 130				'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_SELECT, 
 131				'DISPLAY_WIDTH' => 40, 'DISPLAY_HEIGHT' => 1,
 132				'IS_NULL' => false, 
 133				'DEFAULT' => 0,
 134				'BOUNDS_CHOICE_LIST' => array(
 135					_t('Not accessible to public') => 0,
 136					_t('Accessible to public') => 1
 137				),
 138				'LIST' => 'access_statuses',
 139				'LABEL' => _t('Access'), 'DESCRIPTION' => _t('Indicates if representation is accessible to the public or not. ')
 140		),
 141		'status' => array(
 142				'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_SELECT, 
 143				'DISPLAY_WIDTH' => 40, 'DISPLAY_HEIGHT' => 1,
 144				'IS_NULL' => false, 
 145				'DEFAULT' => 0,
 146				'BOUNDS_CHOICE_LIST' => array(
 147					_t('Newly created') => 0,
 148					_t('Editing in progress') => 1,
 149					_t('Editing complete - pending review') => 2,
 150					_t('Review in progress') => 3,
 151					_t('Completed') => 4
 152				),
 153				'LIST' => 'workflow_statuses',
 154				'LABEL' => _t('Status'), 'DESCRIPTION' => _t('Indicates the current state of the representation.')
 155		),
 156		'rank' => array(
 157				'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_FIELD, 
 158				'DISPLAY_WIDTH' => 10, 'DISPLAY_HEIGHT' => 1,
 159				'IS_NULL' => false, 
 160				'DEFAULT' => '',
 161				'LABEL' => _t('Sort order'), 'DESCRIPTION' => _t('Sort order'),
 162		)
 163 	)
 164);
 165
 166class ca_object_representations extends BundlableLabelableBaseModelWithAttributes implements IBundleProvider {
 167	# ---------------------------------
 168	# --- Object attribute properties
 169	# ---------------------------------
 170	# Describe structure of content object's properties - eg. database fields and their
 171	# associated types, what modes are supported, et al.
 172	#
 173
 174	# ------------------------------------------------------
 175	# --- Basic object parameters
 176	# ------------------------------------------------------
 177	# what table does this class represent?
 178	protected $TABLE = 'ca_object_representations';
 179	      
 180	# what is the primary key of the table?
 181	protected $PRIMARY_KEY = 'representation_id';
 182
 183	# ------------------------------------------------------
 184	# --- Properties used by standard editing scripts
 185	# 
 186	# These class properties allow generic scripts to properly display
 187	# records from the table represented by this class
 188	#
 189	# ------------------------------------------------------
 190
 191	# Array of fields to display in a listing of records from this table
 192	protected $LIST_FIELDS = array('media');
 193
 194	# When the list of "list fields" above contains more than one field,
 195	# the LIST_DELIMITER text is displayed between fields as a delimiter.
 196	# This is typically a comma or space, but can be any string you like
 197	protected $LIST_DELIMITER = ' ';
 198
 199	# What you'd call a single record from this table (eg. a "person")
 200	protected $NAME_SINGULAR;
 201
 202	# What you'd call more than one record from this table (eg. "people")
 203	protected $NAME_PLURAL;
 204
 205	# List of fields to sort listing of records by; you can use 
 206	# SQL 'ASC' and 'DESC' here if you like.
 207	protected $ORDER_BY = array('media');
 208
 209	# Maximum number of record to display per page in a listing
 210	protected $MAX_RECORDS_PER_PAGE = 20; 
 211
 212	# How do you want to page through records in a listing: by number pages ordered
 213	# according to your setting above? Or alphabetically by the letters of the first
 214	# LIST_FIELD?
 215	protected $PAGE_SCHEME = 'alpha'; # alpha [alphabetical] or num [numbered pages; default]
 216
 217	# If you want to order records arbitrarily, add a numeric field to the table and place
 218	# its name here. The generic list scripts can then use it to order table records.
 219	protected $RANK = 'rank';
 220	
 221	
 222	# ------------------------------------------------------
 223	# Hierarchical table properties
 224	# ------------------------------------------------------
 225	protected $HIERARCHY_TYPE				=	null;
 226	protected $HIERARCHY_LEFT_INDEX_FLD 	= 	null;
 227	protected $HIERARCHY_RIGHT_INDEX_FLD 	= 	null;
 228	protected $HIERARCHY_PARENT_ID_FLD		=	null;
 229	protected $HIERARCHY_DEFINITION_TABLE	=	null;
 230	protected $HIERARCHY_ID_FLD				=	null;
 231	protected $HIERARCHY_POLY_TABLE			=	null;
 232	
 233	# ------------------------------------------------------
 234	# Change logging
 235	# ------------------------------------------------------
 236	protected $UNIT_ID_FIELD = null;
 237	protected $LOG_CHANGES_TO_SELF = true;
 238	protected $LOG_CHANGES_USING_AS_SUBJECT = array(
 239		"FOREIGN_KEYS" => array(
 240		
 241		),
 242		"RELATED_TABLES" => array(
 243		
 244		)
 245	);
 246	
 247	# ------------------------------------------------------
 248	# Labeling
 249	# ------------------------------------------------------
 250	protected $LABEL_TABLE_NAME = 'ca_object_representation_labels';
 251	
 252	# ------------------------------------------------------
 253	# Attributes
 254	# ------------------------------------------------------
 255	protected $ATTRIBUTE_TYPE_ID_FLD = 'type_id';								// name of type field for this table - attributes system uses this to determine via ca_metadata_type_restrictions which attributes are applicable to rows of the given type
 256	protected $ATTRIBUTE_TYPE_LIST_CODE = 'object_representation_types';		// list code (ca_lists.list_code) of list defining types for this table
 257
 258	# ------------------------------------------------------
 259	# $FIELDS contains information about each field in the table. The order in which the fields
 260	# are listed here is the order in which they will be returned using getFields()
 261
 262	protected $FIELDS;
 263	
 264	# ------------------------------------------------------
 265	# ID numbering
 266	# ------------------------------------------------------
 267	protected $ID_NUMBERING_ID_FIELD = 'idno';				// name of field containing user-defined identifier
 268	protected $ID_NUMBERING_SORT_FIELD = 'idno_sort';		// name of field containing version of identifier for sorting (is normalized with padding to sort numbers properly)
 269
 270	# ------------------------------------------------------
 271	# Search
 272	# ------------------------------------------------------
 273	protected $SEARCH_CLASSNAME = 'ObjectRepresentationSearch';
 274	protected $SEARCH_RESULT_CLASSNAME = 'ObjectRepresentationSearchResult';
 275	
 276	# ------------------------------------------------------
 277	# --- Constructor
 278	#
 279	# This is a function called when a new instance of this object is created. This
 280	# standard constructor supports three calling modes:
 281	#
 282	# 1. If called without parameters, simply creates a new, empty objects object
 283	# 2. If called with a single, valid primary key value, creates a new objects object and loads
 284	#    the record identified by the primary key value
 285	#
 286	# ------------------------------------------------------
 287	public function __construct($pn_id=null) {
 288		parent::__construct($pn_id);	# call superclass constructor
 289	}
 290	# ------------------------------------------------------
 291	protected function initLabelDefinitions() {
 292		parent::initLabelDefinitions();
 293		$this->BUNDLES['ca_objects'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Related objects'));
 294		$this->BUNDLES['ca_entities'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Related entities'));
 295		$this->BUNDLES['ca_places'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Related places'));
 296		$this->BUNDLES['ca_occurrences'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Related occurrences'));
 297		$this->BUNDLES['ca_representation_annotations'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Related annotations'));
 298		$this->BUNDLES['ca_list_items'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Related vocabulary terms'));
 299		$this->BUNDLES['ca_object_representations_media_display'] = array('type' => 'special', 'repeating' => false, 'label' => _t('Media and preview images'));
 300	}
 301	# ------------------------------------------------------
 302	public function insert() {
 303		// reject if media is empty
 304		if ($this->mediaIsEmpty()) {
 305			$this->postError(2710, _t('No media was specified'), 'ca_object_representations->insert()');
 306			return false;
 307		}
 308		
 309		// do insert
 310		if ($vn_rc = parent::insert()) {
 311			$va_media_info = $this->getMediaInfo('media', 'original');
 312			$this->set('md5', $va_media_info['MD5']);
 313			$va_media_info = $this->getMediaInfo('media');
 314			$this->set('original_filename', $va_media_info['ORIGINAL_FILENAME']);
 315			
 316			$vn_rc = parent::update($pa_options);
 317		}
 318		
 319		return $vn_rc;
 320	}
 321	# ------------------------------------------------------
 322	public function update($pa_options=null) {
 323		if ($vn_rc = parent::update($pa_options)) {
 324			$va_media_info = $this->getMediaInfo('media', 'original');
 325			$this->set('md5', $va_media_info['MD5']);
 326			$va_media_info = $this->getMediaInfo('media');
 327			$this->set('original_filename', $va_media_info['ORIGINAL_FILENAME']);
 328			
 329			$vn_rc = parent::update($pa_options);
 330		}
 331		
 332		return $vn_rc;
 333	}
 334	# ------------------------------------------------------
 335	public function delete($pn_delete_related=false) {
 336		return parent::delete($pn_delete_related);
 337	}
 338	# ------------------------------------------------------
 339	/**
 340	 * Returns true if the media field is set to a non-empty file
 341	 **/
 342	public function mediaIsEmpty() {
 343		if (!($vs_media_path = $this->getMediaPath('media', 'original'))) {
 344			$vs_media_path = $this->get('media');
 345		}
 346		if ($vs_media_path) {
 347			if (file_exists($vs_media_path) && (filesize($vs_media_path) > 0)) {
 348				return false;
 349			}
 350		}
 351		// is it a URL?
 352		if ($this->_CONFIG->get('allow_fetching_of_media_from_remote_urls')) {
 353			if  (isURL($vs_media_path)) {
 354				return false;
 355			}
 356		}
 357		return true;
 358	}
 359	# ------------------------------------------------------
 360	# Annotations
 361	# ------------------------------------------------------
 362	/**
 363	 * Returns annotation type code for currently loaded representation
 364	 * Type codes are based upon the mimetype of the representation's media as defined in the annotation_types.conf file
 365	 * 
 366	 * If you pass the options $pn_representation_id parameter then the returned type is for the specified representation rather
 367	 * than the currently loaded one.
 368	 */
 369 	public function getAnnotationType($pn_representation_id=null) {
 370 		if (!$pn_representation_id) {
 371			$t_rep = $this;
 372		} else {
 373			$t_rep = new ca_object_representations($pn_representation_id);
 374		}
 375 		
 376 		$va_media_info = $t_rep->getMediaInfo('media');
 377 		if (!isset($va_media_info['INPUT'])) { return null; }
 378 		if (!isset($va_media_info['INPUT']['MIMETYPE'])) { return null; }
 379 		
 380 		$vs_mimetype = $va_media_info['INPUT']['MIMETYPE'];
 381 		
 382 		$o_type_config = Configuration::load($this->getAppConfig()->get('annotation_type_config'));
 383 		$va_mappings = $o_type_config->getAssoc('mappings');
 384 		
 385 		return $va_mappings[$vs_mimetype];
 386 	}
 387 	# ------------------------------------------------------
 388 	public function getAnnotationPropertyCoderInstance($ps_type) {
 389 		return ca_representation_annotations::getPropertiesCoderInstance($ps_type);
 390 	}
 391 	# ------------------------------------------------------
 392 	/**
 393 	 * Returns number of annotations attached to current representation
 394 	 *
 395 	 * @param array $pa_options Optional array of options. Supported options are:
 396 	 *			checkAccess - array of access codes to filter count by. Only annotations with an access value set to one of the specified values will be counted.
 397 	 * @return int Number of annotations
 398 	 */
 399 	public function getAnnotationCount($pa_options=null) {
 400 		if (!($vn_representation_id = $this->getPrimaryKey())) { return null; }
 401 		
 402 		if (!is_array($pa_options)) { $pa_options = array(); }
 403 		
 404 		if (!($o_coder = $this->getAnnotationPropertyCoderInstance($this->getAnnotationType()))) {
 405 			// does not support annotations
 406 			return null;
 407 		}
 408 		
 409 		$vs_access_sql = '';
 410 		if (is_array($pa_options['checkAccess']) && sizeof($pa_options['checkAccess'])) {
 411			$vs_access_sql = ' AND cra.access IN ('.join(',', $pa_options['checkAccess']).')';
 412		}
 413		
 414 		$o_db = $this->getDb();
 415 		
 416 		$qr_annotations = $o_db->query("
 417 			SELECT 	cra.annotation_id, cra.locale_id, cra.props, cra.representation_id, cra.user_id, cra.type_code, cra.access, cra.status
 418 			FROM ca_representation_annotations cra
 419 			WHERE
 420 				cra.representation_id = ? {$vs_access_sql}
 421 		", (int)$vn_representation_id);
 422 		
 423 		return $qr_annotations->numRows();
 424 	}
 425 	# ------------------------------------------------------
 426 	/**
 427 	 * Returns data for annotations attached to current representation
 428 	 *
 429 	 * @param array $pa_options Optional array of options. Supported options are:
 430 	 *			checkAccess - array of access codes to filter count by. Only annotations with an access value set to one of the specified values will be returned
 431 	 * @return array List of annotations attached to the current representation, key'ed on annotation_id. Value is an array will all values; annotation labels are returned in the current locale.
 432 	 */
 433 	public function getAnnotations($pa_options=null) {
 434 		if (!($vn_representation_id = $this->getPrimaryKey())) { return null; }
 435 		
 436 		if (!is_array($pa_options)) { $pa_options = array(); }
 437 		
 438 		if (!($o_coder = $this->getAnnotationPropertyCoderInstance($this->getAnnotationType()))) {
 439 			// does not support annotations
 440 			return null;
 441 		}
 442 		$o_db = $this->getDb();
 443 		
 444 		$vs_access_sql = '';
 445 		if (is_array($pa_options['checkAccess']) && sizeof($pa_options['checkAccess'])) {
 446			$vs_access_sql = ' AND cra.access IN ('.join(',', $pa_options['checkAccess']).')';
 447		}
 448 		
 449 		$qr_annotations = $o_db->query("
 450 			SELECT 	cra.annotation_id, cra.locale_id, cra.props, cra.representation_id, cra.user_id, cra.type_code, cra.access, cra.status
 451 			FROM ca_representation_annotations cra
 452 			WHERE
 453 				cra.representation_id = ? {$vs_access_sql}
 454 		", (int)$vn_representation_id);
 455 		
 456 		$vs_sort_by_property = $this->getAnnotationSortProperty();
 457 		$va_annotations = array();
 458 		while($qr_annotations->nextRow()) {
 459 			$va_tmp = $qr_annotations->getRow();
 460 			$o_coder->setPropertyValues($qr_annotations->getVars('props'));
 461 			foreach($o_coder->getPropertyList() as $vs_property) {
 462 				$va_tmp[$vs_property] = $o_coder->getProperty($vs_property);
 463 				$va_tmp[$vs_property.'_raw'] = $o_coder->getProperty($vs_property, true);
 464 			}
 465 			
 466 			if (!($vs_sort_key = $va_tmp[$vs_sort_by_property])) {
 467 				$vs_sort_key = '_default_';
 468 			}
 469 			
 470 			$va_annotations[$vs_sort_key][$qr_annotations->get('annotation_id')] = $va_tmp;
 471 		}
 472 		
 473 		// get annotation labels
 474 		$qr_annotation_labels = $o_db->query("
 475 			SELECT 	cral.annotation_id, cral.locale_id, cral.name, cral.label_id
 476 			FROM ca_representation_annotation_labels cral
 477 			INNER JOIN ca_representation_annotations AS cra ON cra.annotation_id = cral.annotation_id
 478 			WHERE
 479 				cra.representation_id = ? AND cral.is_preferred = 1
 480 		", (int)$vn_representation_id);
 481 		
 482 		$va_labels = array();
 483 		while($qr_annotation_labels->nextRow()) {
 484 			$va_labels[$qr_annotation_labels->get('annotation_id')][$qr_annotation_labels->get('locale_id')] = $qr_annotation_labels->get('name');
 485 		}
 486 		
 487 		if (!isset($pa_options['dontExtraValuesByUserLocale']) || !$pa_options['dontExtraValuesByUserLocale']) {
 488 			$va_labels = caExtractValuesByUserLocale($va_labels);
 489 		}
 490 		
 491 		ksort($va_annotations, SORT_REGULAR);
 492 		$va_sorted_annotations = array();
 493 		foreach($va_annotations as $vs_key => $va_values) {
 494 			foreach($va_values as $va_val) {
 495 				$va_val['labels'] = $va_labels[$va_val['annotation_id']] ? $va_labels[$va_val['annotation_id']] : array();
 496 				$va_sorted_annotations[$va_val['annotation_id']] = $va_val;
 497 			}
 498 		}
 499 		return $va_sorted_annotations;
 500 	} 
 501 	# ------------------------------------------------------
 502 	public function addAnnotation($pn_locale_id, $pn_user_id, $pa_properties, $pn_status, $pn_access) {
 503 		if (!($vn_representation_id = $this->getPrimaryKey())) { return null; }
 504 		
 505 		if (!($o_coder = $this->getAnnotationPropertyCoderInstance($this->getAnnotationType()))) {
 506 			// does not support annotations
 507 			return null;
 508 		}
 509 		
 510 		foreach($o_coder->getPropertyList() as $vs_property) {
 511			if (!$o_coder->setProperty($vs_property, $pa_properties[$vs_property])) {
 512				// error setting values
 513				$this->errors = $o_coder->errors;
 514				return false;
 515			}
 516		}
 517		
 518		if (!$o_coder->validate()) {
 519			$this->errors = $o_coder->errors;
 520			return false;
 521		}
 522 		
 523 		$t_annotation = new ca_representation_annotations();
 524 		$t_annotation->setMode(ACCESS_WRITE);
 525 		
 526 		$t_annotation->set('representation_id', $vn_representation_id);
 527 		$t_annotation->set('type_code', $o_coder->getType());
 528 		$t_annotation->set('locale_id', $pn_locale_id);
 529 		$t_annotation->set('user_id', $pn_user_id);
 530 		$t_annotation->set('status', $pn_status);
 531 		$t_annotation->set('access', $pn_access);
 532 		
 533 		$t_annotation->insert();
 534 		
 535 		if ($t_annotation->numErrors()) {
 536			$this->errors = $t_annotation->errors;
 537			return false;
 538		}
 539		foreach($o_coder->getPropertyList() as $vs_property) {
 540			$t_annotation->setPropertyValue($vs_property, $o_coder->getProperty($vs_property));
 541		}
 542		
 543		$t_annotation->update();
 544 		
 545 		if ($t_annotation->numErrors()) {
 546			$this->errors = $t_annotation->errors;
 547			return false;
 548		}
 549		
 550 		
 551 		return $t_annotation->getPrimaryKey();
 552 	}
 553 	# ------------------------------------------------------
 554 	public function editAnnotation($pn_annotation_id, $pn_locale_id, $pa_properties, $pn_status, $pn_access) {
 555 		if (!($vn_representation_id = $this->getPrimaryKey())) { return null; }
 556 	
 557 		if (!($o_coder = $this->getAnnotationPropertyCoderInstance($this->getAnnotationType()))) {
 558 			// does not support annotations
 559 			return null;
 560 		}
 561 		foreach($o_coder->getPropertyList() as $vs_property) {
 562			if (!$o_coder->setProperty($vs_property, $pa_properties[$vs_property])) {
 563				// error setting values
 564				$this->errors = $o_coder->errors;
 565				return false;
 566			}
 567		}
 568		
 569		if (!$o_coder->validate()) {
 570			$this->errors = $o_coder->errors;
 571			return false;
 572		}
 573		
 574 		$t_annotation = new ca_representation_annotations($pn_annotation_id);
 575 		if ($t_annotation->getPrimaryKey() && ($t_annotation->get('representation_id') == $vn_representation_id)) {
 576 			foreach($o_coder->getPropertyList() as $vs_property) {
 577 				$t_annotation->setPropertyValue($vs_property, $o_coder->getProperty($vs_property));
 578 			}
 579 		
 580 			$t_annotation->setMode(ACCESS_WRITE);
 581 		
 582			$t_annotation->set('type_code', $o_coder->getType());
 583			$t_annotation->set('locale_id', $pn_locale_id);
 584			$t_annotation->set('status', $pn_status);
 585			$t_annotation->set('access', $pn_access);
 586			
 587			$t_annotation->update();
 588			if ($t_annotation->numErrors()) {
 589				$this->errors = $t_annotation->errors;
 590				return false;
 591			}
 592			
 593			return true;
 594 		}
 595 		
 596 		return false;
 597 	}
 598 	# ------------------------------------------------------
 599 	public function removeAnnotation($pn_annotation_id) {
 600 		if (!($vn_representation_id = $this->getPrimaryKey())) { return null; }
 601 		
 602 		$t_annotation = new ca_representation_annotations($pn_annotation_id);
 603 		if ($t_annotation->get('representation_id') == $vn_representation_id) {
 604 			$t_annotation->setMode(ACCESS_WRITE);
 605 			$t_annotation->delete(true);
 606 			
 607 			if ($t_annotation->numErrors()) {
 608 				$this->errors = $t_annotation->errors;
 609 				return false;
 610 			}
 611 			return true;
 612 		}
 613 		
 614 		return false;
 615 	}
 616 	# ------------------------------------------------------
 617 	#
 618 	# ------------------------------------------------------
 619 	/**
 620 	 * Return list of representations that are related to the object(s) this representation is related to
 621 	 */ 
 622 	public function getOtherRepresentationsInRelatedObjects() {
 623 		if (!($vn_representation_id = $this->getPrimaryKey())) { return null; }
 624 		
 625 		$o_db = $this->getDb();
 626 		
 627 		$qr_res = $o_db->query("
 628 			SELECT *
 629 			FROM ca_object_representations cor
 630 			INNER JOIN ca_objects_x_object_representations AS coxor ON cor.representation_id = coxor.representation_id
 631 			WHERE
 632 				coxor.object_id IN (
 633 					SELECT object_id
 634 					FROM ca_objects_x_object_representations 
 635 					WHERE 
 636 						representation_id = ?
 637 				)
 638 		", (int)$vn_representation_id);
 639 		
 640 		$va_reps = array();
 641 		while($qr_res->nextRow()) {
 642 			$va_reps[$qr_res->get('representation_id')] = $qr_res->getRow();
 643 		}
 644 		
 645 		return $va_reps;
 646 	}
 647 	# ------------------------------------------------------
 648 	/**
 649 	 * Bundle generator - called from BundlableLabelableBaseModelWithAttributes::getBundleFormHTML()
 650 	 */
 651	protected function getRepresentationAnnotationHTMLFormBundle($po_request, $ps_form_name, $ps_placement_code, $pa_bundle_settings=null, $pa_options=null) {
 652		//if (!$this->getAnnotationType()) { return; }	// don't show bundle if this representation doesn't support annotations
 653		
 654		$o_view = new View($po_request, $po_request->getViewsDirectoryPath().'/bundles/');
 655		$t_item = new ca_representation_annotations();
 656		$t_item_label = new ca_representation_annotation_labels();
 657		
 658		$o_view->setVar('id_prefix', $ps_form_name);
 659		$o_view->setVar('placement_code', $ps_placement_code);		// pass placement code
 660		
 661		$o_view->setVar('t_item', $t_item);
 662		$o_view->setVar('t_item_label', $t_item_label);
 663		
 664		$o_view->setVar('t_subject', $this);
 665		$o_view->setVar('settings', $pa_bundle_settings);
 666		
 667		$va_inital_values = array();
 668		if (sizeof($va_items = $this->getAnnotations(array('dontExtraValuesByUserLocale' => true)))) {
 669			$t_rel = $this->getAppDatamodel()->getInstanceByTableName('ca_representation_annotations', true);
 670			$vs_rel_pk = $t_rel->primaryKey();
 671			foreach ($va_items as $vn_id => $va_item) {
 672				if (!($vs_label = $va_item['labels'][$va_item['locale_id']])) { $vs_label = ''; }
 673				$va_inital_values[$va_item[$t_item->primaryKey()]] = array_merge($va_item, array('id' => $va_item[$vs_rel_pk], 'item_type_id' => $va_item['item_type_id'], 'relationship_type_id' => $va_item['relationship_type_id'], 'label' => $vs_label));
 674			}
 675		}
 676		
 677		$o_view->setVar('initialValues', $va_inital_values);
 678		
 679		return $o_view->render('ca_representation_annotations.php');
 680	}	
 681 	# ------------------------------------------------------
 682 	/**
 683 	 *
 684 	 */
 685 	protected function _processRepresentationAnnotations($po_request, $ps_form_prefix, $ps_placement_code) {
 686 		$va_rel_items = $this->getAnnotations(array('dontExtraValuesByUserLocale' => true));
 687		$o_coder = $this->getAnnotationPropertyCoderInstance($this->getAnnotationType());
 688		foreach($va_rel_items as $vn_id => $va_rel_item) {
 689			$this->clearErrors();
 690			if (strlen($vn_status = $po_request->getParameter($ps_placement_code.$ps_form_prefix.'_ca_representation_annotations_status_'.$va_rel_item['annotation_id'], pString))) {
 691				$vn_access = $po_request->getParameter($ps_placement_code.$ps_form_prefix.'_ca_representation_annotations_access_'.$va_rel_item['annotation_id'], pInteger);
 692				$vn_locale_id = $po_request->getParameter($ps_placement_code.$ps_form_prefix.'_ca_representation_annotations_locale_id_'.$va_rel_item['annotation_id'], pInteger);
 693				
 694				$va_properties = array();
 695				foreach($o_coder->getPropertyList() as $vs_property) {
 696					$va_properties[$vs_property] = $po_request->getParameter($ps_placement_code.$ps_form_prefix.'_ca_representation_annotations_'.$vs_property.'_'.$va_rel_item['annotation_id'], pString);
 697				}
 698
 699				// edit annotation
 700				$this->editAnnotation($va_rel_item['annotation_id'], $vn_locale_id, $va_properties, $vn_status, $vn_access);
 701			
 702				if ($this->numErrors()) {
 703					$po_request->addActionErrors($this->errors(), 'ca_representation_annotations', $va_rel_item['annotation_id']);
 704				} else {
 705					// try to add/edit label
 706					if ($vs_label = $po_request->getParameter($ps_placement_code.$ps_form_prefix.'_ca_representation_annotations_label_'.$va_rel_item['annotation_id'], pString)) {
 707						$t_annotation = new ca_representation_annotations($va_rel_item['annotation_id']);
 708						if ($t_annotation->getPrimaryKey()) {
 709							$t_annotation->setMode(ACCESS_WRITE);
 710							
 711							$va_pref_labels = $t_annotation->getPreferredLabels(array($vn_locale_id), false);
 712							
 713							if (sizeof($va_pref_labels)) {
 714								// edit existing label
 715								foreach($va_pref_labels as $vn_annotation_dummy_id => $va_labels_by_locale) {
 716									foreach($va_labels_by_locale as $vn_locale_dummy_id => $va_labels) {
 717										$t_annotation->editLabel($va_labels[0]['label_id'], array('name' => $vs_label), $vn_locale_id, null, true);
 718									}
 719								}
 720							} else {
 721								// create new label
 722								$t_annotation->addLabel(array('name' => $vs_label), $vn_locale_id, null, true);
 723							}
 724							
 725							if ($t_annotation->numErrors()) {
 726								$po_request->addActionErrors($t_annotation->errors(), 'ca_representation_annotations', 'new_'.$vn_c);
 727							}
 728						}
 729					}
 730				}
 731			} else {
 732				// is it a delete key?
 733				$this->clearErrors();
 734				if (($po_request->getParameter($ps_placement_code.$ps_form_prefix.'_ca_representation_annotations_'.$va_rel_item['annotation_id'].'_delete', pInteger)) > 0) {
 735					// delete!
 736					$this->removeAnnotation($va_rel_item['annotation_id']);
 737					if ($this->numErrors()) {
 738						$po_request->addActionErrors($this->errors(), 'ca_representation_annotations', $va_rel_item['annotation_id']);
 739					}
 740				}
 741			}
 742		}
 743 		
 744 		// check for new annotations to add
 745 		foreach($_REQUEST as $vs_key => $vs_value ) {
 746			if (!preg_match('/^'.$ps_placement_code.$ps_form_prefix.'_ca_representation_annotations_status_new_([\d]+)/', $vs_key, $va_matches)) { continue; }
 747			$vn_c = intval($va_matches[1]);
 748			if (strlen($vn_status = $po_request->getParameter($ps_placement_code.$ps_form_prefix.'_ca_representation_annotations_status_new_'.$vn_c, pString)) > 0) {
 749				$vn_access = $po_request->getParameter($ps_placement_code.$ps_form_prefix.'_ca_representation_annotations_access_new_'.$vn_c, pInteger);
 750				$vn_locale_id = $po_request->getParameter($ps_placement_code.$ps_form_prefix.'_ca_representation_annotations_locale_id_new_'.$vn_c, pInteger);
 751				
 752				$va_properties = array();
 753				foreach($o_coder->getPropertyList() as $vs_property) {
 754					$va_properties[$vs_property] = $po_request->getParameter($ps_placement_code.$ps_form_prefix.'_ca_representation_annotations_'.$vs_property.'_new_'.$vn_c, pString);
 755				}
 756				
 757				// create annotation
 758				$vn_annotation_id = $this->addAnnotation($vn_locale_id, $po_request->getUserID(), $va_properties, $vn_status, $vn_access);
 759				
 760				if ($this->numErrors()) {
 761					$po_request->addActionErrors($this->errors(), 'ca_representation_annotations', 'new_'.$vn_c);
 762				} else {
 763					// try to add label
 764					if ($vs_label = $po_request->getParameter($ps_placement_code.$ps_form_prefix.'_ca_representation_annotations_label_new_'.$vn_c, pString)) {
 765						$t_annotation = new ca_representation_annotations($vn_annotation_id);
 766						if ($t_annotation->getPrimaryKey()) {
 767							$t_annotation->setMode(ACCESS_WRITE);
 768							$t_annotation->addLabel(array('name' => $vs_label), $vn_locale_id, null, true);
 769							
 770							if ($t_annotation->numErrors()) {
 771								$po_request->addActionErrors($t_annotation->errors(), 'ca_representation_annotations', 'new_'.$vn_c);
 772							}
 773						}
 774					}
 775				}
 776			}
 777		}
 778		
 779		return true;
 780 	}
 781 	# ------------------------------------------------------
 782 	public function useBundleBasedAnnotationEditor() {
 783 		if (!($o_coder = $this->getAnnotationPropertyCoderInstance($this->getAnnotationType()))) {
 784 			// does not support annotations
 785 			return false;
 786 		}
 787 		
 788 		return $o_coder->useBundleBasedAnnotationEditor();
 789 	}
 790 	# ------------------------------------------------------
 791 	public function getAnnotationSortProperty() {
 792 		if (!($o_coder = $this->getAnnotationPropertyCoderInstance($this->getAnnotationType()))) {
 793 			// does not support annotations
 794 			return false;
 795 		}
 796 		
 797 		return $o_coder->getAnnotationSortProperty();
 798 	}
 799 	# ------------------------------------------------------
 800 	# Annotation display
 801 	# ------------------------------------------------------
 802 	public function getDisplayMediaWithAnnotationsHTMLBundle($po_request, $ps_version, $pa_options=null) {
 803 		if (!is_array($pa_options)) { $pa_options = array(); }
 804 		$pa_options['poster_frame_url'] = $this->getMediaUrl('media', 'medium');
 805 		
 806 		if (!($vs_tag = $this->getMediaTag('media', $ps_version, $pa_options))) {
 807 			return '';
 808 		}
 809 		
 810 		$o_view = new View($po_request, $po_request->getViewsDirectoryPath().'/bundles/');
 811		
 812		$o_view->setVar('viewer_tag', $vs_tag);
 813		$o_view->setVar('annotations', $this->getAnnotations($pa_options));
 814		
 815		return $o_view->render('ca_object_representations_display_with_annotations.php', false);
 816 	}
 817 	# ------------------------------------------------------
 818 	# Multifiles
 819 	# ------------------------------------------------------
 820 	/**
 821 	 *
 822 	 */
 823 	public function addFile($ps_filepath, $ps_resource_path='/', $pb_allow_duplicates=true) {
 824 		if(!$this->getPrimaryKey()) { return null; }
 825 		if (!trim($ps_resource_path)) { $ps_resource_path = '/'; }
 826 		
 827 		$t_multifile = new ca_object_representation_multifiles();
 828 		if (!$pb_allow_duplicates) {
 829 			if ($t_multifile->load(array('resource_path' => $ps_resource_path, 'representation_id' => $this->getPrimaryKey()))) {
 830 				return null;
 831 			}
 832 		}
 833 		$t_multifile->setMode(ACCESS_WRITE);
 834 		$t_multifile->set('representation_id', $this->getPrimaryKey());
 835 		$t_multifile->set('media', $ps_filepath);
 836 		$t_multifile->set('resource_path', $ps_resource_path);
 837 		
 838 		$t_multifile->insert();
 839 		
 840 		if ($t_multifile->numErrors()) {
 841 			$this->errors = array_merge($this->errors, $t_multifile->errors);
 842 			return false;
 843 		}
 844 		
 845 		return $t_multifile;
 846 	}
 847 	# ------------------------------------------------------
 848 	/**
 849 	 *
 850 	 */
 851 	public function removeFile($pn_multifile_id) {
 852 		if(!$this->getPrimaryKey()) { return null; }
 853 		
 854 		$t_multifile = new ca_object_representation_multifiles($pn_multifile_id);
 855 		
 856 		if ($t_multifile->get('representation_id') == $this->getPrimaryKey()) {
 857 			$t_multifile->setMode(ACCESS_WRITE);
 858 			$t_multifile->delete();
 859 			
 860			if ($t_multifile->numErrors()) {
 861				$this->errors = array_merge($this->errors, $t_multifile->errors);
 862				return false;
 863			}
 864		} else {
 865			$this->postError(2720, _t('File is not part of this representation'), 'ca_object_representations->removeFile()');
 866			return false;
 867		}
 868		return true;
 869 	}
 870 	# ------------------------------------------------------
 871 	/**
 872 	 *
 873 	 */
 874 	public function removeAllFiles() {
 875 		if(!$this->getPrimaryKey()) { return null; }
 876 		
 877 		$va_file_ids = array_keys($this->getFileList());
 878 		
 879 		foreach($va_file_ids as $vn_id) {
 880 			$this->removeFile($vn_id);
 881 			
 882 			if($this->numErrors()) {
 883 				return false;
 884 			}
 885 		}
 886 		
 887 		return true;
 888 	}
 889 	# ------------------------------------------------------
 890 	/**
 891 	 *
 892 	 */
 893 	public function getFileList($pn_representation_id=null, $pn_start=null, $pn_num_files=null, $pa_versions=null) {
 894 		if(!($vn_representation_id = $pn_representation_id)) { 
 895 			if (!($vn_representation_id = $this->getPrimaryKey())) {
 896 				return null; 
 897 			}
 898 		}
 899 		
 900 		if (!is_array($pa_versions)) {
 901 			$pa_versions = array('preview');
 902 		}
 903 		
 904 		$vs_limit_sql = '';
 905 		if (!is_null($pn_start) && !is_null($pn_num_files)) {
 906 			if (($pn_start >= 0) && ($pn_num_files >= 1)) {
 907 				$vs_limit_sql = "LIMIT {$pn_start}, {$pn_num_files}";
 908 			}
 909 		}
 910 		
 911 		$o_db= $this->getDb();
 912 		$qr_res = $o_db->query("
 913 			SELECT *
 914 			FROM ca_object_representation_multifiles
 915 			WHERE
 916 				representation_id = ?
 917 			{$vs_limit_sql}
 918 		", (int)$vn_representation_id);
 919 		
 920 		$va_files = array();
 921 		while($qr_res->nextRow()) {
 922 			$vn_multifile_id = $qr_res->get('multifile_id');
 923 			$va_files[$vn_multifile_id] = $qr_res->getRow();
 924 			unset($va_files[$vn_multifile_id]['media']);
 925 			
 926 			foreach($pa_versions as $vn_i => $vs_version) {
 927 				$va_files[$vn_multifile_id][$vs_version.'_tag'] = $qr_res->getMediaTag('media', $vs_version);
 928 				$va_files[$vn_multifile_id][$vs_version.'_url'] = $qr_res->getMediaUrl('media', $vs_version);
 929 				
 930 				$va_info = $qr_res->getMediaInfo('media', $vs_version);
 931 				$va_files[$vn_multifile_id][$vs_version.'_width'] = $va_info['WIDTH'];
 932 				$va_files[$vn_multifile_id][$vs_version.'_height'] = $va_info['HEIGHT'];
 933 			}
 934 		}
 935 		return $va_files;
 936 	}
 937 	# ------------------------------------------------------
 938 	/**
 939 	 *
 940 	 */
 941 	public function getFileInstance($pn_multifile_id) {
 942 		if(!$this->getPrimaryKey()) { return null; }
 943 	
 944 		$t_multifile = new ca_object_representation_multifiles($pn_multifile_id);
 945 		
 946 		if ($t_multifile->get('representation_id') == $this->getPrimaryKey()) {
 947 			return $t_multifile;
 948 		}
 949 		return null;
 950 	}
 951 	# ------------------------------------------------------
 952 	/**
 953 	 *
 954 	 */
 955 	public function numFiles($pn_representation_id=null) { 		
 956 		if(!($vn_representation_id = $pn_representation_id)) { 
 957 			if (!($vn_representation_id = $this->getPrimaryKey())) {
 958 				return null; 
 959 			}
 960 		}
 961 		
 962 		$o_db= $this->getDb();
 963 		$qr_res = $o_db->query("
 964 			SELECT count(*) c
 965 			FROM ca_object_representation_multifiles
 966 			WHERE
 967 				representation_id = ?
 968 		", (int)$vn_representation_id);
 969 		
 970 		if($qr_res->nextRow()) {
 971 			return intval($qr_res->get('c'));
 972 		}
 973 		return 0;
 974 	}
 975 	# ------------------------------------------------------
 976 	/**
 977 	 * Matching method to ca_objects::getRepresentations(), except this one only returns a single representation - the currently loaded one
 978 	 */
 979 	public function getRepresentations($pa_versions=null, $pa_version_sizes=null, $pa_options=null) {
 980 		if (!($vn_object_id = $this->getPrimaryKey())) { return null; }
 981 		if (!is_array($pa_options)) { $pa_options = array(); }
 982 		
 983 		if (!is_array($pa_versions)) { 
 984 			$pa_versions = array('preview170');
 985 		}
 986 		
 987 		$o_db = $this->getDb();
 988 		
 989 		$qr_reps = $o_db->query("
 990 			SELECT caor.representation_id, caor.media, caor.access, caor.status, l.name, caor.locale_id, caor.media_metadata, caor.type_id
 991 			FROM ca_object_representations caor
 992 			LEFT JOIN ca_locales AS l ON caor.locale_id = l.locale_id
 993 			WHERE
 994 				caor.representation_id = ? 
 995 				{$vs_is_primary_sql}
 996 				{$vs_access_sql}
 997 			ORDER BY
 998 				l.name ASC 
 999 		", (int)$this->getPrimaryKey());
1000 		
1001 		$va_reps = array();
1002 		while($qr_reps->nextRow()) {
1003 			$va_tmp = $qr_reps->getRow();
1004 			$va_tmp['tags'] = array();
1005 			$va_tmp['urls'] = array();
1006 			
1007 			$va_info = $qr_reps->getMediaInfo('media');
1008 			$va_tmp['info'] = array('original_filename' => $va_info['ORIGINAL_FILENAME']);
1009 			foreach ($pa_versions as $vs_version) {
1010 				if (is_array($pa_version_sizes) && isset($pa_version_sizes[$vs_version])) {
1011 					$vn_width = $pa_version_sizes[$vs_version]['width'];
1012 					$vn_height = $pa_version_sizes[$vs_version]['height'];
1013 				} else {
1014 					$vn_width = $vn_height = 0;
1015 				}
1016 				
1017 				if ($vn_width && $vn_height) {
1018 					$va_tmp['tags'][$vs_version] = $qr_reps->getMediaTag('media', $vs_version, array_merge($pa_options, array('viewer_width' => $vn_width, 'viewer_height' => $vn_height)));
1019 				} else {
1020 					$va_tmp['tags'][$vs_version] = $qr_reps->getMediaTag('media', $vs_version, $pa_options);
1021 				}
1022 				$va_tmp['urls'][$vs_version] = $qr_reps->getMediaUrl('media', $vs_version);
1023 				$va_tmp['paths'][$vs_version] = $qr_reps->getMediaPath('media', $vs_version);
1024 				$va_tmp['info'][$vs_version] = $qr_reps->getMediaInfo('media', $vs_version);
1025 				
1026 				$va_dimensions = array();
1027 				if (isset($va_tmp['info'][$vs_version]['WIDTH']) && isset($va_tmp['info'][$vs_version]['HEIGHT'])) {
1028					if (($vn_w = $va_tmp['info'][$vs_version]['WIDTH']) && ($vn_h = $va_tmp['info'][$vs_version]['WIDTH'])) {
1029						$va_dimensions[] = $va_tmp['info'][$vs_version]['WIDTH'].'p x '.$va_tmp['info'][$vs_version]['HEIGHT'].'p';
1030					}
1031				}
1032 				if (isset($va_tmp['info'][$vs_version]['PROPERTIES']['bitdepth']) && ($vn_depth = $va_tmp['info'][$vs_version]['PROPERTIES']['bitdepth'])) {
1033 					$va_dimensions[] = intval($vn_depth).' bpp';
1034 				}
1035 				if (isset($va_tmp['info'][$vs_version]['PROPERTIES']['colorspace']) && ($vs_colorspace = $va_tmp['info'][$vs_version]['PROPERTIES']['colorspace'])) {
1036 					$va_dimensions[] = $vs_colorspace;
1037 				}
1038 				if (isset($va_tmp['info'][$vs_version]['PROPERTIES']['resolution']) && is_array($va_resolution = $va_tmp['info'][$vs_version]['PROPERTIES']['resolution'])) {
1039 					if (isset($va_resolution['x']) && isset($va_resolution['y']) && $va_resolution['x'] && $va_resolution['y']) {
1040 						// TODO: units for resolution? right now assume pixels per inch
1041 						if ($va_resolution['x'] == $va_resolution['y']) {
1042 							$va_dimensions[] = $va_resolution['x'].'ppi';
1043 						} else {
1044 							$va_dimensions[] = $va_resolution['x'].'x'.$va_resolution['y'].'ppi';
1045 						}
1046 					}
1047 				}
1048 				if (isset($va_tmp['info'][$vs_version]['PROPERTIES']['duration']) && ($vn_duration = $va_tmp['info'][$vs_version]['PROPERTIES']['duration'])) {
1049 					$va_dimensions[] = sprintf("%4.1f", $vn_duration).'s';
1050 				}
1051 				if (isset($va_tmp['info'][$vs_version]['PROPERTIES']['pages']) && ($vn_pages = $va_tmp['info'][$vs_version]['PROPERTIES']['pages'])) {
1052 					$va_dimensions[] = $vn_pages.' '.(($vn_pages == 1) ? _t('page') : _t('pages'));
1053 				}
1054 				if (!isset($va_tmp['info'][$vs_version]['PROPERTIES']['filesize']) || !($vn_filesize = $va_tmp['info'][$vs_version]['PROPERTIES']['filesize'])) {
1055 					$vn_filesize = @filesize($qr_reps->getMediaPath('media', $vs_version));
1056 				}
1057 				if ($vn_filesize) {
1058 					$va_dimensions[] = sprintf("%4.1f", $vn_filesize/(1024*1024)).'mb';
1059 				}
1060 				$va_tmp['dimensions'][$vs_version] = join('; ', $va_dimensions);
1061 			}
1062 			
1063 				
1064			if (isset($va_info['INPUT']['FETCHED_FROM']) && ($vs_fetched_from_url = $va_info['INPUT']['FETCHED_FROM'])) {
1065				$va_tmp['fetched_from'] = $vs_fetched_from_url;
1066				$va_tmp['fetched_on'] = (int)$va_info['INPUT']['FETCHED_ON'];
1067			}
1068 			
1069 			$va_tmp['num_multifiles'] = $this->numFiles($this->get('representation_id'));
1070 			$va_reps[] = $va_tmp;
1071 		}
1072 		return $va_reps;
1073 	}
1074 	# ------------------------------------------------------
1075 	/**
1076 	 * 
1077 	 */
1078 	public function getRepresentationViewerHTMLBundle($po_request, $pa_options=null) {
1079 		$va_access_values = (isset($pa_options['access']) && is_array($pa_options['access'])) ? $pa_options['access'] : array();	
1080 		$vs_display_type = (isset($pa_options['display']) && $pa_options['display']) ? $pa_options['display'] : 'media_overlay';	
1081 		$vs_container_dom_id = (isset($pa_options['containerID']) && $pa_options['containerID']) ? $pa_options['containerID'] : null;	
1082 		$vn_object_id = (isset($pa_options['object_id']) && $pa_options['object_id']) ? $pa_options['object_id'] : null;
1083 		
1084 		$t_object = new ca_objects($vn_object_id);
1085		$o_view = new View($po_request, $po_request->getViewsDirectoryPath().'/bundles/');
1086		
1087		$o_view->setVar('containerID', $vs_container_dom_id);
1088		
1089 		if (($vn_representation_id = $this->getPrimaryKey()) && ((!sizeof($va_access_values) || in_array($this->get('access'), $va_access_values)))) { 		// check rep access
1090			$va_rep_display_info = caGetMediaDisplayInfo($vs_display_type, $this->getMediaInfo('media', 'INPUT', 'MIMETYPE'));
1091			$va_rep_display_info['poster_frame_url'] = $this->getMediaUrl('media', $va_rep_display_info['poster_frame_version']);
1092
1093			$o_view->setVar('num_multifiles', $this->numFiles());
1094						
1095			$o_view->setVar('display_options', $va_rep_display_info);
1096			$o_view->setVar('representation_id', $pn_representation_id);
1097			$o_view->setVar('t_object_representation', $this);
1098			$o_view->setVar('versions', $va_versions = $this->getMediaVersions('media'));
1099			
1100			$t_media = new Media();
1101			$o_view->setVar('version_type', $t_media->getMimetypeTypename($this->getMediaInfo('media', 'original', 'MIMETYPE')));
1102		
1103			if ($t_object->getPrimaryKey()) { 
1104				$o_view->setVar('reps', $va_reps = $t_object->getRepresentations(array('icon')));
1105				
1106				$vn_next_rep = $vn_prev_rep = null;
1107				
1108				$va_rep_list = array_values($va_reps);
1109				foreach($va_rep_list as $vn_i => $va_rep) {
1110					if ($va_rep['representation_id'] == $vn_representation_id) {
1111						if (isset($va_rep_list[$vn_i - 1])) {
1112							$vn_prev_rep = $va_rep_list[$vn_i - 1]['representation_id'];
1113						}
1114						if (isset($va_rep_list[$vn_i + 1])) {
1115							$vn_next_rep = $va_rep_list[$vn_i + 1]['representation_id'];
1116						}
1117						$o_view->setVar('representation_index', $vn_i + 1);
1118					}
1119				}
1120				$o_view->setVar('previous_representation_id', $vn_prev_rep);
1121				$o_view->setVar('next_representation_id', $vn_next_rep);
1122			}	
1123			$ps_version 	= $po_request->getParameter('version', pString);
1124			if (!in_array($ps_version, $va_versions)) { 
1125				if (!($ps_version = $va_rep_display_info['display_version'])) { $ps_version = null; }
1126			}
1127			$o_view->setVar('version', $ps_version);
1128			$o_view->setVar('version_info', $this->getMediaInfo('media', $ps_version));
1129			
1130 			$o_view->setVar('t_object', $t_object);
1131		}
1132		return $o_view->render('representation_viewer_html.php');
1133 	}
1134 	# ------------------------------------------------------
1135	/** 
1136	 * Returns HTML form bundle (for use in a ca_object_representations editor form) for media
1137	 *
1138	 * @param HTTPRequest $po_request The current request
1139	 * @param string $ps_form_name
1140	 * @param string $ps_placement_code
1141	 * @param array $pa_bundle_settings
1142	 * @param array $pa_options Array of options. Supported options are 
1143	 *			noCache = If set to true then label cache is bypassed; default is true
1144	 *
1145	 * @return string Rendered HTML bundle
1146	 */
1147	public function getMediaDisplayHTMLFormBundle($po_request, $ps_form_name, $ps_placement_code, $pa_bundle_settings=null, $pa_options=null) {
1148		global $g_ui_locale;
1149		
1150		$o_view = new View($po_request, $po_request->getViewsDirectoryPath().'/bundles/');
1151		
1152		if(!is_array($pa_options)) { $pa_options = array(); }
1153		
1154		$o_view->setVar('id_prefix', $ps_form_name.'_media_display');
1155		$o_view->setVar('placement_code', $ps_placement_code);		// pass placement code
1156		
1157		$o_view->setVar('settings', $pa_bundle_settings);
1158		
1159		$o_view->setVar('t_subject', $this);
1160		
1161		$va_media_info = $this->getMediaInfo('media');
1162		$o_view->setVar('representation_typename', $va_media_info['original']['PROPERTIES']['typename']);
1163		$o_view->setVar('representation_num_multifiles', $this->numFiles());
1164		
1165		
1166		return $o_view->render('ca_object_representations_media_display.php');
1167	}
1168	# ------------------------------------------------------
1169}
1170?>