PageRenderTime 58ms CodeModel.GetById 16ms RepoModel.GetById 1ms app.codeStats 0ms

/app/models/ca_objects.php

https://bitbucket.org/Sinfin/pawtucket
PHP | 1171 lines | 828 code | 105 blank | 238 comment | 145 complexity | c495a080fd1fa7d38769206b6f350445 MD5 | raw file
Possible License(s): LGPL-3.0, GPL-3.0

Large files files are truncated, but you can click here to view the full file

  1. <?php
  2. /** ---------------------------------------------------------------------
  3. * app/models/ca_objects.php : table access class for table ca_objects
  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. require_once(__CA_LIB_DIR__."/ca/IBundleProvider.php");
  36. require_once(__CA_LIB_DIR__."/ca/BundlableLabelableBaseModelWithAttributes.php");
  37. require_once(__CA_MODELS_DIR__."/ca_object_representations.php");
  38. require_once(__CA_MODELS_DIR__."/ca_objects_x_object_representations.php");
  39. BaseModel::$s_ca_models_definitions['ca_objects'] = array(
  40. 'NAME_SINGULAR' => _t('object'),
  41. 'NAME_PLURAL' => _t('objects'),
  42. 'FIELDS' => array(
  43. 'object_id' => array(
  44. 'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_HIDDEN,
  45. 'IDENTITY' => true, 'DISPLAY_WIDTH' => 10, 'DISPLAY_HEIGHT' => 1,
  46. 'IS_NULL' => false,
  47. 'DEFAULT' => '',
  48. 'LABEL' => 'Object id', 'DESCRIPTION' => 'Unique identifier for the object.'
  49. ),
  50. 'parent_id' => array(
  51. 'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_OMIT,
  52. 'DISPLAY_WIDTH' => 10, 'DISPLAY_HEIGHT' => 1,
  53. 'IS_NULL' => true,
  54. 'DEFAULT' => '',
  55. 'LABEL' => 'Parent id', 'DESCRIPTION' => 'Identifier of parent object; is null if object is root of hierarchy.'
  56. ),
  57. 'hier_object_id' => array(
  58. 'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_OMIT,
  59. 'DISPLAY_WIDTH' => 10, 'DISPLAY_HEIGHT' => 1,
  60. 'IS_NULL' => false,
  61. 'DEFAULT' => '',
  62. 'LABEL' => 'Object hierarchy', 'DESCRIPTION' => 'Identifier of object that is root of the object hierarchy.'
  63. ),
  64. 'lot_id' => array(
  65. 'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_HIDDEN,
  66. 'DISPLAY_WIDTH' => 10, 'DISPLAY_HEIGHT' => 1,
  67. 'IS_NULL' => true,
  68. 'DEFAULT' => '',
  69. 'LABEL' => _t('Lot'), 'DESCRIPTION' => _t('Lot this object belongs to; is null if object is not part of a lot.')
  70. ),
  71. 'locale_id' => array(
  72. 'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_SELECT,
  73. 'DISPLAY_WIDTH' => 40, 'DISPLAY_HEIGHT' => 1,
  74. 'IS_NULL' => true,
  75. 'DISPLAY_FIELD' => array('ca_locales.name'),
  76. 'DEFAULT' => '',
  77. 'LABEL' => _t('Locale'), 'DESCRIPTION' => _t('The locale from which the object originates.')
  78. ),
  79. 'source_id' => array(
  80. 'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_SELECT,
  81. 'DISPLAY_WIDTH' => 10, 'DISPLAY_HEIGHT' => 1,
  82. 'IS_NULL' => true,
  83. 'DEFAULT' => '',
  84. 'LIST_CODE' => 'object_sources',
  85. 'LABEL' => _t('Source'), 'DESCRIPTION' => _t('Administrative source of object. This value is often used to indicate the administrative sub-division or legacy database from which the object originates, but can also be re-tasked for use as a simple classification tool if needed.')
  86. ),
  87. 'type_id' => array(
  88. 'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_SELECT,
  89. 'DISPLAY_WIDTH' => 10, 'DISPLAY_HEIGHT' => 1,
  90. 'IS_NULL' => false,
  91. 'DEFAULT' => '',
  92. 'LIST_CODE' => 'object_types',
  93. 'LABEL' => _t('Type'), 'DESCRIPTION' => _t('The type of the object. In CollectiveAccess every object has a single "instrinsic" type that determines the set of descriptive, technical and administrative metadata that can be applied to it. As such this type is "low-level" and directly tied to the form of the object - eg. photograph, book, analog video recording, etc.')
  94. ),
  95. 'idno' => array(
  96. 'FIELD_TYPE' => FT_TEXT, 'DISPLAY_TYPE' => DT_FIELD,
  97. 'DISPLAY_WIDTH' => 40, 'DISPLAY_HEIGHT' => 1,
  98. 'IS_NULL' => false,
  99. 'DEFAULT' => '',
  100. 'LABEL' => _t('Object identifier'), 'DESCRIPTION' => _t('A unique alphanumeric identifier for this object. This is usually equivalent to the "accession number" in museum settings.'),
  101. 'BOUNDS_LENGTH' => array(0,255)
  102. ),
  103. 'idno_sort' => array(
  104. 'FIELD_TYPE' => FT_TEXT, 'DISPLAY_TYPE' => DT_OMIT,
  105. 'DISPLAY_WIDTH' => 40, 'DISPLAY_HEIGHT' => 1,
  106. 'IS_NULL' => false,
  107. 'DEFAULT' => '',
  108. 'LABEL' => 'Sortable object identifier', 'DESCRIPTION' => 'Value used for sorting objects on identifier value.',
  109. 'BOUNDS_LENGTH' => array(0,255)
  110. ),
  111. 'item_status_id' => array(
  112. 'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_SELECT,
  113. 'DISPLAY_WIDTH' => 40, 'DISPLAY_HEIGHT' => 1,
  114. 'IS_NULL' => true,
  115. 'DEFAULT' => '',
  116. 'LIST_CODE' => 'object_statuses',
  117. 'LABEL' => _t('Accession status'), 'DESCRIPTION' => _t('Indicates accession/collection status of object. (eg. accessioned, pending accession, loan, non-accessioned item, etc.)')
  118. ),
  119. 'acquisition_type_id' => array(
  120. 'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_SELECT,
  121. 'DISPLAY_WIDTH' => 40, 'DISPLAY_HEIGHT' => 1,
  122. 'IS_NULL' => true,
  123. 'DEFAULT' => '',
  124. 'LIST_CODE' => 'object_acq_types',
  125. 'LABEL' => _t('Acquisition method'), 'DESCRIPTION' => _t('Indicates method employed to acquire the object.')
  126. ),
  127. 'source_info' => array(
  128. 'FIELD_TYPE' => FT_VARS, 'DISPLAY_TYPE' => DT_OMIT,
  129. 'DISPLAY_WIDTH' => 88, 'DISPLAY_HEIGHT' => 15,
  130. 'IS_NULL' => false,
  131. 'DEFAULT' => '',
  132. 'LABEL' => 'Source information', 'DESCRIPTION' => 'Serialized array used to store source information for object information retrieved via web services [NOT IMPLEMENTED YET].'
  133. ),
  134. 'hier_left' => array(
  135. 'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_OMIT,
  136. 'DISPLAY_WIDTH' => 10, 'DISPLAY_HEIGHT' => 1,
  137. 'IS_NULL' => false,
  138. 'DEFAULT' => '',
  139. 'LABEL' => 'Hierarchical index - left bound', 'DESCRIPTION' => 'Left-side boundary for nested set-style hierarchical indexing; used to accelerate search and retrieval of hierarchical record sets.'
  140. ),
  141. 'hier_right' => array(
  142. 'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_OMIT,
  143. 'DISPLAY_WIDTH' => 10, 'DISPLAY_HEIGHT' => 1,
  144. 'IS_NULL' => false,
  145. 'DEFAULT' => '',
  146. 'LABEL' => 'Hierarchical index - right bound', 'DESCRIPTION' => 'Right-side boundary for nested set-style hierarchical indexing; used to accelerate search and retrieval of hierarchical record sets.'
  147. ),
  148. 'extent' => array(
  149. 'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_FIELD,
  150. 'DISPLAY_WIDTH' => 20, 'DISPLAY_HEIGHT' => 1,
  151. 'IS_NULL' => false,
  152. 'DEFAULT' => '',
  153. 'LABEL' => _t('Extent'), 'DESCRIPTION' => _t('The extent of the object. This is typically the number of discrete items that compose the object represented by this record. It is stored as a whole number (eg. 1, 2, 3...).')
  154. ),
  155. 'extent_units' => array(
  156. 'FIELD_TYPE' => FT_TEXT, 'DISPLAY_TYPE' => DT_FIELD,
  157. 'DISPLAY_WIDTH' => 20, 'DISPLAY_HEIGHT' => 1,
  158. 'IS_NULL' => false,
  159. 'DEFAULT' => '',
  160. 'LABEL' => _t('Extent units'), 'DESCRIPTION' => _t('Units of extent value. (eg. pieces, items, components, reels, etc.)'),
  161. 'BOUNDS_LENGTH' => array(0,255)
  162. ),
  163. 'access' => array(
  164. 'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_SELECT,
  165. 'DISPLAY_WIDTH' => 40, 'DISPLAY_HEIGHT' => 1,
  166. 'IS_NULL' => false,
  167. 'DEFAULT' => 0,
  168. 'BOUNDS_CHOICE_LIST' => array(
  169. _t('Not accessible to public') => 0,
  170. _t('Accessible to public') => 1
  171. ),
  172. 'LIST' => 'access_statuses',
  173. 'LABEL' => _t('Access'), 'DESCRIPTION' => _t('Indicates if object is accessible to the public or not.')
  174. ),
  175. 'status' => array(
  176. 'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_SELECT,
  177. 'DISPLAY_WIDTH' => 40, 'DISPLAY_HEIGHT' => 1,
  178. 'IS_NULL' => false,
  179. 'DEFAULT' => 0,
  180. 'BOUNDS_CHOICE_LIST' => array(
  181. _t('Newly created') => 0,
  182. _t('Editing in progress') => 1,
  183. _t('Editing complete - pending review') => 2,
  184. _t('Review in progress') => 3,
  185. _t('Completed') => 4
  186. ),
  187. 'LIST' => 'workflow_statuses',
  188. 'LABEL' => _t('Status'), 'DESCRIPTION' => _t('Indicates the current state of the object record.')
  189. ),
  190. 'deleted' => array(
  191. 'FIELD_TYPE' => FT_BIT, 'DISPLAY_TYPE' => DT_OMIT,
  192. 'DISPLAY_WIDTH' => 10, 'DISPLAY_HEIGHT' => 1,
  193. 'IS_NULL' => false,
  194. 'DEFAULT' => 0,
  195. 'LABEL' => _t('Is deleted?'), 'DESCRIPTION' => _t('Indicates if the object is deleted or not.'),
  196. 'BOUNDS_VALUE' => array(0,1)
  197. ),
  198. 'rank' => array(
  199. 'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_FIELD,
  200. 'DISPLAY_WIDTH' => 10, 'DISPLAY_HEIGHT' => 1,
  201. 'IS_NULL' => false,
  202. 'DEFAULT' => '',
  203. 'LABEL' => _t('Sort order'), 'DESCRIPTION' => _t('Sort order'),
  204. )
  205. )
  206. );
  207. class ca_objects extends BundlableLabelableBaseModelWithAttributes implements IBundleProvider {
  208. # ---------------------------------
  209. # --- Object attribute properties
  210. # ---------------------------------
  211. # Describe structure of content object's properties - eg. database fields and their
  212. # associated types, what modes are supported, et al.
  213. #
  214. # ------------------------------------------------------
  215. # --- Basic object parameters
  216. # ------------------------------------------------------
  217. # what table does this class represent?
  218. protected $TABLE = 'ca_objects';
  219. # what is the primary key of the table?
  220. protected $PRIMARY_KEY = 'object_id';
  221. # ------------------------------------------------------
  222. # --- Properties used by standard editing scripts
  223. #
  224. # These class properties allow generic scripts to properly display
  225. # records from the table represented by this class
  226. #
  227. # ------------------------------------------------------
  228. # Array of fields to display in a listing of records from this table
  229. protected $LIST_FIELDS = array('idno');
  230. # When the list of "list fields" above contains more than one field,
  231. # the LIST_DELIMITER text is displayed between fields as a delimiter.
  232. # This is typically a comma or space, but can be any string you like
  233. protected $LIST_DELIMITER = ' ';
  234. # What you'd call a single record from this table (eg. a "person")
  235. protected $NAME_SINGULAR;
  236. # What you'd call more than one record from this table (eg. "people")
  237. protected $NAME_PLURAL;
  238. # List of fields to sort listing of records by; you can use
  239. # SQL 'ASC' and 'DESC' here if you like.
  240. protected $ORDER_BY = array('idno');
  241. # Maximum number of record to display per page in a listing
  242. protected $MAX_RECORDS_PER_PAGE = 20;
  243. # How do you want to page through records in a listing: by number pages ordered
  244. # according to your setting above? Or alphabetically by the letters of the first
  245. # LIST_FIELD?
  246. protected $PAGE_SCHEME = 'alpha'; # alpha [alphabetical] or num [numbered pages; default]
  247. # If you want to order records arbitrarily, add a numeric field to the table and place
  248. # its name here. The generic list scripts can then use it to order table records.
  249. protected $RANK = 'rank';
  250. # ------------------------------------------------------
  251. # Hierarchical table properties
  252. # ------------------------------------------------------
  253. protected $HIERARCHY_TYPE = __CA_HIER_TYPE_ADHOC_MONO__;
  254. protected $HIERARCHY_LEFT_INDEX_FLD = 'hier_left';
  255. protected $HIERARCHY_RIGHT_INDEX_FLD = 'hier_right';
  256. protected $HIERARCHY_PARENT_ID_FLD = 'parent_id';
  257. protected $HIERARCHY_DEFINITION_TABLE = 'ca_objects';
  258. protected $HIERARCHY_ID_FLD = 'hier_object_id';
  259. protected $HIERARCHY_POLY_TABLE = null;
  260. # ------------------------------------------------------
  261. # Change logging
  262. # ------------------------------------------------------
  263. protected $UNIT_ID_FIELD = null;
  264. protected $LOG_CHANGES_TO_SELF = true;
  265. protected $LOG_CHANGES_USING_AS_SUBJECT = array(
  266. "FOREIGN_KEYS" => array(
  267. 'lot_id'
  268. ),
  269. "RELATED_TABLES" => array(
  270. )
  271. );
  272. # ------------------------------------------------------
  273. # Labeling
  274. # ------------------------------------------------------
  275. protected $LABEL_TABLE_NAME = 'ca_object_labels';
  276. # ------------------------------------------------------
  277. # Attributes
  278. # ------------------------------------------------------
  279. 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
  280. protected $ATTRIBUTE_TYPE_LIST_CODE = 'object_types'; // list code (ca_lists.list_code) of list defining types for this table
  281. # ------------------------------------------------------
  282. # Self-relations
  283. # ------------------------------------------------------
  284. protected $SELF_RELATION_TABLE_NAME = 'ca_objects_x_objects';
  285. # ------------------------------------------------------
  286. # ID numbering
  287. # ------------------------------------------------------
  288. protected $ID_NUMBERING_ID_FIELD = 'idno'; // name of field containing user-defined identifier
  289. protected $ID_NUMBERING_SORT_FIELD = 'idno_sort'; // name of field containing version of identifier for sorting (is normalized with padding to sort numbers properly)
  290. # ------------------------------------------------------
  291. # Search
  292. # ------------------------------------------------------
  293. protected $SEARCH_CLASSNAME = 'ObjectSearch';
  294. protected $SEARCH_RESULT_CLASSNAME = 'ObjectSearchResult';
  295. # ------------------------------------------------------
  296. # $FIELDS contains information about each field in the table. The order in which the fields
  297. # are listed here is the order in which they will be returned using getFields()
  298. protected $FIELDS;
  299. # ------------------------------------------------------
  300. # --- Constructor
  301. #
  302. # This is a function called when a new instance of this object is created. This
  303. # standard constructor supports three calling modes:
  304. #
  305. # 1. If called without parameters, simply creates a new, empty objects object
  306. # 2. If called with a single, valid primary key value, creates a new objects object and loads
  307. # the record identified by the primary key value
  308. #
  309. # ------------------------------------------------------
  310. public function __construct($pn_id=null) {
  311. parent::__construct($pn_id);
  312. }
  313. # ------------------------------------------------------
  314. protected function initLabelDefinitions() {
  315. parent::initLabelDefinitions();
  316. $this->BUNDLES['ca_object_representations'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Media representations'));
  317. $this->BUNDLES['ca_objects'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Related objects'));
  318. $this->BUNDLES['ca_entities'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Related entities'));
  319. $this->BUNDLES['ca_places'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Related places'));
  320. $this->BUNDLES['ca_occurrences'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Related occurrences'));
  321. $this->BUNDLES['ca_collections'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Related collections'));
  322. $this->BUNDLES['ca_storage_locations'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Related storage locations'));
  323. $this->BUNDLES['ca_loans'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Related loans'));
  324. $this->BUNDLES['ca_movements'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Related movements'));
  325. $this->BUNDLES['ca_object_lots'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Related lot'));
  326. $this->BUNDLES['ca_object_events'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Related events'));
  327. $this->BUNDLES['ca_list_items'] = array('type' => 'related_table', 'repeating' => true, 'label' => _t('Related vocabulary terms'));
  328. $this->BUNDLES['ca_sets'] = array('type' => 'special', 'repeating' => true, 'label' => _t('Sets'));
  329. $this->BUNDLES['hierarchy_navigation'] = array('type' => 'special', 'repeating' => false, 'label' => _t('Hierarchy navigation'));
  330. $this->BUNDLES['hierarchy_location'] = array('type' => 'special', 'repeating' => false, 'label' => _t('Location in hierarchy'));
  331. }
  332. # ------------------------------------------------------
  333. public function delete($pb_delete_related=false){
  334. // nuke related representations
  335. foreach($this->getRepresentations() as $va_rep){
  336. $this->removeRepresentation($va_rep["representation_id"]);
  337. }
  338. return parent::delete($pb_delete_related);
  339. }
  340. # ------------------------------------------------------
  341. /**
  342. * @param array $pa_options
  343. * duplicate_media
  344. */
  345. public function duplicate($pa_options=null) {
  346. $vb_we_set_transaction = false;
  347. if (!$this->inTransaction()) {
  348. $this->setTransaction($o_t = new Transaction($this->getDb()));
  349. $vb_we_set_transaction = true;
  350. } else {
  351. $o_t = $this->getTransaction();
  352. }
  353. if ($t_dupe = parent::duplicate($pa_options)) {
  354. $vb_duplicate_media = isset($pa_options['duplicate_media']) && $pa_options['duplicate_media'];
  355. if ($vb_duplicate_media) {
  356. // Try to link representations
  357. $o_db = $this->getDb();
  358. $qr_res = $o_db->query("
  359. SELECT *
  360. FROM ca_objects_x_object_representations
  361. WHERE object_id = ?
  362. ", (int)$this->getPrimaryKey());
  363. $va_reps = array();
  364. while($qr_res->nextRow()) {
  365. $va_reps[$qr_res->get('representation_id')] = $qr_res->getRow();
  366. }
  367. $t_object_x_rep = new ca_objects_x_object_representations();
  368. foreach($va_reps as $vn_representation_id => $va_rep) {
  369. $t_object_x_rep->setMode(ACCESS_WRITE);
  370. $va_rep['object_id'] = $t_dupe->getPrimaryKey();
  371. $t_object_x_rep->set($va_rep);
  372. $t_object_x_rep->insert();
  373. if ($t_object_x_rep->numErrors()) {
  374. $this->errors = $t_object_x_rep->errors;
  375. if ($vb_we_set_transaction) { $this->removeTransaction(false);}
  376. return false;
  377. }
  378. }
  379. }
  380. }
  381. if ($vb_we_set_transaction) { $this->removeTransaction(true);}
  382. return $t_dupe;
  383. }
  384. # ------------------------------------------------------
  385. # ------------------------------------------------------
  386. # Representations
  387. # ------------------------------------------------------
  388. /**
  389. * Returns information about representations linked to the currently loaded object. Use this if you want to get the urls, tags and other information for all representations associated with a given object.
  390. *
  391. * @param array $pa_versions An array of media versions to include information for. If you omit this then a single version, 'preview170', is assumed by default.
  392. * @param array $pa_version_sizes Optional array of sizes to force specific versions to. The array keys are version names; the values are arrays with two keys: 'width' and 'height'; if present these values will be used in lieu of the actual values in the database
  393. * @param array $pa_options An optional array of options to use when getting representation information. Supported options are:
  394. * return_primary_only - If true then only the primary representation will be returned
  395. * return_with_access - Set to an array of access values to filter representation through; only representations with an access value in the list will be returned
  396. * checkAccess - synonym for return_with_access
  397. * .. and options supported by getMediaTag() .. [they are passed through]
  398. *
  399. */
  400. public function getRepresentations($pa_versions=null, $pa_version_sizes=null, $pa_options=null) {
  401. if (!($vn_object_id = $this->getPrimaryKey())) { return null; }
  402. if (!is_array($pa_options)) { $pa_options = array(); }
  403. if (!is_array($pa_versions)) {
  404. $pa_versions = array('preview170');
  405. }
  406. if (isset($pa_options['return_primary_only']) && $pa_options['return_primary_only']) {
  407. $vs_is_primary_sql = ' AND (caoor.is_primary = 1)';
  408. } else {
  409. $vs_is_primary_sql = '';
  410. }
  411. if ($pa_options['checkAccess']) { $pa_options['return_with_access'] = $pa_options['checkAccess']; }
  412. if (is_array($pa_options['return_with_access']) && sizeof($pa_options['return_with_access']) > 0) {
  413. $vs_access_sql = ' AND (caor.access IN ('.join(", ", $pa_options['return_with_access']).'))';
  414. } else {
  415. $vs_access_sql = '';
  416. }
  417. $o_db = $this->getDb();
  418. $qr_reps = $o_db->query("
  419. SELECT caor.representation_id, caor.media, caoor.is_primary, caor.access, caor.status, l.name, caor.locale_id, caor.media_metadata, caor.type_id, caor.idno, caor.idno_sort
  420. FROM ca_object_representations caor
  421. INNER JOIN ca_objects_x_object_representations AS caoor ON caor.representation_id = caoor.representation_id
  422. LEFT JOIN ca_locales AS l ON caor.locale_id = l.locale_id
  423. WHERE
  424. caoor.object_id = ?
  425. {$vs_is_primary_sql}
  426. {$vs_access_sql}
  427. ORDER BY
  428. caoor.rank, caoor.is_primary DESC
  429. ", (int)$vn_object_id);
  430. $va_reps = array();
  431. $t_rep = new ca_object_representations();
  432. while($qr_reps->nextRow()) {
  433. $vn_rep_id = $qr_reps->get('representation_id');
  434. $va_tmp = $qr_reps->getRow();
  435. $va_tmp['tags'] = array();
  436. $va_tmp['urls'] = array();
  437. $va_info = $qr_reps->getMediaInfo('media');
  438. $va_tmp['info'] = array('original_filename' => $va_info['ORIGINAL_FILENAME']);
  439. foreach ($pa_versions as $vs_version) {
  440. if (is_array($pa_version_sizes) && isset($pa_version_sizes[$vs_version])) {
  441. $vn_width = $pa_version_sizes[$vs_version]['width'];
  442. $vn_height = $pa_version_sizes[$vs_version]['height'];
  443. } else {
  444. $vn_width = $vn_height = 0;
  445. }
  446. if ($vn_width && $vn_height) {
  447. $va_tmp['tags'][$vs_version] = $qr_reps->getMediaTag('media', $vs_version, array_merge($pa_options, array('viewer_width' => $vn_width, 'viewer_height' => $vn_height)));
  448. } else {
  449. $va_tmp['tags'][$vs_version] = $qr_reps->getMediaTag('media', $vs_version, $pa_options);
  450. }
  451. $va_tmp['urls'][$vs_version] = $qr_reps->getMediaUrl('media', $vs_version);
  452. $va_tmp['paths'][$vs_version] = $qr_reps->getMediaPath('media', $vs_version);
  453. $va_tmp['info'][$vs_version] = $qr_reps->getMediaInfo('media', $vs_version);
  454. $va_tmp['dimensions'][$vs_version] = caGetRepresentationDimensionsForDisplay($qr_reps, 'original', array());
  455. }
  456. if (isset($va_info['INPUT']['FETCHED_FROM']) && ($vs_fetched_from_url = $va_info['INPUT']['FETCHED_FROM'])) {
  457. $va_tmp['fetched_from'] = $vs_fetched_from_url;
  458. $va_tmp['fetched_on'] = (int)$va_info['INPUT']['FETCHED_ON'];
  459. }
  460. $va_tmp['num_multifiles'] = $t_rep->numFiles($vn_rep_id);
  461. $va_reps[$vn_rep_id] = $va_tmp;
  462. }
  463. $va_labels = $t_rep->getPreferredDisplayLabelsForIDs(array_keys($va_reps));
  464. foreach($va_labels as $vn_rep_id => $vs_label) {
  465. $va_reps[$vn_rep_id]['label'] = $vs_label;
  466. }
  467. return $va_reps;
  468. }
  469. # ------------------------------------------------------
  470. /**
  471. * Finds and returns information about representations meeting the specified criteria. Returns information in the same format as getRepresentations()
  472. *
  473. * @param array $pa_options Array of criteria options to use when selecting representations. Options include:
  474. * mimetypes = array of mimetypes to return
  475. * sortby = if set, representations are return sorted using the criteria in ascending order. Valid values are 'filesize' (sort by file size), 'duration' (sort by length of time-based media)
  476. * @return array List of representations. Each entry in the list is an associative array of the same format as returned by getRepresentations() and includes properties, tags and urls for the representation.
  477. */
  478. public function findRepresentations($pa_options) {
  479. $va_mimetypes = array();
  480. if (isset($pa_options['mimetypes']) && (is_array($pa_options['mimetypes'])) && (sizeof($pa_options['mimetypes']))) {
  481. $va_mimetypes = array_flip($pa_options['mimetypes']);
  482. }
  483. $vs_sortby = null;
  484. if (isset($pa_options['sortby']) && $pa_options['sortby'] && in_array($pa_options['sortby'], array('filesize', 'duration'))) {
  485. $vs_sortby = $pa_options['sortby'];
  486. }
  487. $va_reps = $this->getRepresentations(array('original'));
  488. $va_found_reps = array();
  489. foreach($va_reps as $vn_i => $va_rep) {
  490. if((sizeof($va_mimetypes)) && isset($va_mimetypes[$va_rep['info']['original']['MIMETYPE']])) {
  491. switch($vs_sortby) {
  492. case 'filesize':
  493. $va_found_reps[$va_rep['info']['original']['FILESIZE']][] = $va_rep;
  494. break;
  495. case 'duration':
  496. $vn_duration = $va_rep['info']['original']['PROPERTIES']['duration'];
  497. $va_found_reps[$vn_duration][] = $va_rep;
  498. break;
  499. default:
  500. $va_found_reps[] = $va_rep;
  501. break;
  502. }
  503. }
  504. }
  505. if ($vs_sortby) {
  506. ksort($va_found_reps);
  507. $va_tmp = array();
  508. foreach($va_found_reps as $va_found_rep_groups) {
  509. foreach($va_found_rep_groups as $va_found_rep) {
  510. $va_tmp[] = $va_found_rep;
  511. }
  512. }
  513. $va_found_reps = $va_tmp;
  514. }
  515. return $va_found_reps;
  516. }
  517. # ------------------------------------------------------
  518. # Representations
  519. # ------------------------------------------------------
  520. /**
  521. *
  522. */
  523. public function getRepresentationIDs($pa_options=null) {
  524. if (!($vn_object_id = $this->getPrimaryKey())) { return null; }
  525. if (!is_array($pa_options)) { $pa_options = array(); }
  526. if (!is_array($pa_versions)) {
  527. $pa_versions = array('preview170');
  528. }
  529. if (isset($pa_options['return_primary_only']) && $pa_options['return_primary_only']) {
  530. $vs_is_primary_sql = ' AND (caoor.is_primary = 1)';
  531. } else {
  532. $vs_is_primary_sql = '';
  533. }
  534. if (is_array($pa_options['return_with_access']) && sizeof($pa_options['return_with_access']) > 0) {
  535. $vs_access_sql = ' AND (caor.access IN ('.join(", ", $pa_options['return_with_access']).'))';
  536. } else {
  537. $vs_access_sql = '';
  538. }
  539. $o_db = $this->getDb();
  540. $qr_reps = $o_db->query("
  541. SELECT caor.representation_id, caoor.is_primary
  542. FROM ca_object_representations caor
  543. INNER JOIN ca_objects_x_object_representations AS caoor ON caor.representation_id = caoor.representation_id
  544. WHERE
  545. caoor.object_id = ?
  546. {$vs_is_primary_sql}
  547. {$vs_access_sql}
  548. ", (int)$vn_object_id);
  549. $va_rep_ids = array();
  550. while($qr_reps->nextRow()) {
  551. $va_rep_ids[$qr_reps->get('representation_id')] = ($qr_reps->get('is_primary') == 1) ? true : false;
  552. }
  553. return $va_rep_ids;
  554. }
  555. # ------------------------------------------------------
  556. /**
  557. * Returns number of representations attached to the currently loaded object
  558. *
  559. * @param array $pa_options Optional array of options. Supported options include:
  560. * return_with_type - A type to restrict the count to. Can be either an integer type_id or item_code string
  561. * return_with_access - An array of access values to restrict counts to
  562. *
  563. * @return integer The number of representations
  564. */
  565. public function getRepresentationCount($pa_options=null) {
  566. if (!($vn_object_id = $this->getPrimaryKey())) { return null; }
  567. if (!is_array($pa_options)) { $pa_options = array(); }
  568. $vs_type_sql = '';
  569. if (isset($pa_options['return_with_type']) && $pa_options['return_with_type']) {
  570. if (!is_numeric($pa_options['return_with_type'])) {
  571. $t_list = new ca_lists();
  572. $pa_options['return_with_type'] = $t_list->getItemIDFromList('object_representation_types', $pa_options['return_with_type']);
  573. }
  574. if (intval($pa_options['return_with_type']) > 0) {
  575. $vs_type_sql = ' AND (caor.type_id = '.intval($pa_options['return_with_type']).')';
  576. }
  577. }
  578. if (is_array($pa_options['return_with_access']) && sizeof($pa_options['return_with_access']) > 0) {
  579. $vs_access_sql = ' AND (caor.access IN ('.join(", ", $pa_options['return_with_access']).'))';
  580. } else {
  581. $vs_access_sql = '';
  582. }
  583. $o_db = $this->getDb();
  584. $qr_reps = $o_db->query("
  585. SELECT count(*) c
  586. FROM ca_object_representations caor
  587. INNER JOIN ca_objects_x_object_representations AS caoor ON caor.representation_id = caoor.representation_id
  588. LEFT JOIN ca_locales AS l ON caor.locale_id = l.locale_id
  589. WHERE
  590. caoor.object_id = ?
  591. {$vs_type_sql}
  592. {$vs_access_sql}
  593. ", (int)$vn_object_id);
  594. $qr_reps->nextRow();
  595. return (int)$qr_reps->get('c');
  596. }
  597. # ------------------------------------------------------
  598. /**
  599. * Returns primary representation for the object; versions specified in $pa_versions are returned. See description
  600. * of getRepresentations() for a description of returned values.
  601. */
  602. public function getPrimaryRepresentation($pa_versions=null, $pa_version_sizes=null, $pa_options=null) {
  603. if (!is_array($pa_options)) { $pa_options = array(); }
  604. if(is_array($va_reps = $this->getRepresentations($pa_versions, $pa_version_sizes, array_merge($pa_options, array('return_primary_only' => 1))))) {
  605. return array_pop($va_reps);
  606. }
  607. return array();
  608. }
  609. # ------------------------------------------------------
  610. /**
  611. * Returns representation_id of primary representation for the object.
  612. */
  613. public function getPrimaryRepresentationID($pa_options=null) {
  614. if (!is_array($pa_options)) { $pa_options = array(); }
  615. $va_rep_ids = $this->getRepresentationIDs(array_merge($pa_options, array('return_primary_only' => 1)));
  616. if (!is_array($va_rep_ids)) { return null; }
  617. foreach($va_rep_ids as $vn_representation_id => $vb_is_primary) {
  618. if ($vb_is_primary) { return $vn_representation_id; }
  619. }
  620. return null;
  621. }
  622. # ------------------------------------------------------
  623. /**
  624. * Returns ca_object_representations instance loaded with primary representation for the current ca_objects row
  625. */
  626. public function getPrimaryRepresentationInstance($pa_options=null) {
  627. if (!is_array($pa_options)) { $pa_options = array(); }
  628. if (!($vn_rep_id = $this->getPrimaryRepresentationID($pa_options))) { return null; }
  629. $t_rep = new ca_object_representations($vn_rep_id);
  630. return ($t_rep->getPrimaryKey()) ? $t_rep : null;
  631. }
  632. # ------------------------------------------------------
  633. /**
  634. * Add media represention to currently loaded object
  635. *
  636. * @param $ps_media_path - the path to the media you want to add
  637. * @param $pn_type_id - the item_id of the representation type, in the ca_list with list_code 'object_represention_types'
  638. * @param $pn_locale_id - the locale_id of the locale of the representation
  639. * @param $pn_status - the status code for the representation (as defined in item_value fields of items in the 'workflow_statuses' ca_list)
  640. * @param $pn_access - the access code for the representation (as defined in item_value fields of items in the 'access_statuses' ca_list)
  641. * @param $pb_is_primary - if set to true, representation is designated "primary." Primary representation are used in cases where only one representation is required (such as search results). If a primary representation is already attached to this object, then it will be changed to non-primary as only one representation can be primary at any given time. If no primary representations exist, then the new representation will always be marked primary no matter what the setting of this parameter (there must always be a primary representation, if representations are defined).
  642. * @param $pa_values - array of attributes to attach to new representation
  643. * @param $pa_options - an array of options passed through to BaseModel::set() when creating the new representation. Currently supported options:
  644. * original_filename - the name of the file being uploaded; will be recorded in the database and used as the filename when the file is subsequently downloaded
  645. * rank - a numeric rank used to order the representations when listed
  646. */
  647. public function addRepresentation($ps_media_path, $pn_type_id, $pn_locale_id, $pn_status, $pn_access, $pb_is_primary, $pa_values=null, $pa_options=null) {
  648. if (!($vn_object_id = $this->getPrimaryKey())) { return null; }
  649. if (!$pn_locale_id) { $pn_locale_id = ca_locales::getDefaultCataloguingLocaleID(); }
  650. $t_rep = new ca_object_representations();
  651. $t_rep->setMode(ACCESS_WRITE);
  652. $t_rep->set('type_id', $pn_type_id);
  653. $t_rep->set('locale_id', $pn_locale_id);
  654. $t_rep->set('status', $pn_status);
  655. $t_rep->set('access', $pn_access);
  656. $t_rep->set('media', $ps_media_path, $pa_options);
  657. if (is_array($pa_values)) {
  658. if (isset($pa_values['idno'])) {
  659. $t_rep->set('idno', $pa_values['idno']);
  660. }
  661. foreach($pa_values as $vs_element => $va_value) {
  662. if (is_array($va_value)) {
  663. // array of values (complex multi-valued attribute)
  664. $t_rep->addAttribute(
  665. array_merge($va_value, array(
  666. 'locale_id' => $pn_locale_id
  667. )), $vs_element);
  668. } else {
  669. // scalar value (simple single value attribute)
  670. if ($va_value) {
  671. $t_rep->addAttribute(array(
  672. 'locale_id' => $pn_locale_id,
  673. $vs_element => $va_value
  674. ), $vs_element);
  675. }
  676. }
  677. }
  678. }
  679. $t_rep->insert();
  680. if ($t_rep->numErrors()) {
  681. $this->errors = array_merge($this->errors, $t_rep->errors());
  682. return false;
  683. }
  684. $vs_label = (isset($pa_values['name']) && $pa_values['name']) ? $pa_values['name'] : '['._t('BLANK').']';
  685. $t_rep->addLabel(array('name' => $vs_label), $pn_locale_id, null, true);
  686. if ($t_rep->numErrors()) {
  687. $this->errors = array_merge($this->errors, $t_rep->errors());
  688. return false;
  689. }
  690. $t_oxor = new ca_objects_x_object_representations();
  691. $t_oxor->setMode(ACCESS_WRITE);
  692. $t_oxor->set('object_id', $vn_object_id);
  693. $t_oxor->set('representation_id', $t_rep->getPrimaryKey());
  694. $t_oxor->set('is_primary', $pb_is_primary ? 1 : 0);
  695. $t_oxor->set('rank', isset($pa_options['rank']) ? (int)$pa_options['rank'] : null);
  696. $t_oxor->insert();
  697. if ($t_oxor->numErrors()) {
  698. $this->errors = array_merge($this->errors, $t_oxor->errors());
  699. $t_rep->delete();
  700. if ($t_rep->numErrors()) {
  701. $this->errors = array_merge($this->errors, $t_rep->errors());
  702. }
  703. return false;
  704. }
  705. return $t_oxor->getPrimaryKey();
  706. }
  707. # ------------------------------------------------------
  708. /**
  709. *
  710. */
  711. public function editRepresentation($pn_representation_id, $ps_media_path, $pn_locale_id, $pn_status, $pn_access, $pb_is_primary, $pa_values=null, $pa_options=null) {
  712. if (!($vn_object_id = $this->getPrimaryKey())) { return null; }
  713. $t_rep = new ca_object_representations();
  714. if (!$t_rep->load(array('representation_id' => $pn_representation_id))) {
  715. $this->postError(750, _t("Representation id=%1 does not exist", $pn_representation_id), "ca_objects->editRepresentation()");
  716. return false;
  717. } else {
  718. $t_rep->setMode(ACCESS_WRITE);
  719. $t_rep->set('locale_id', $pn_locale_id);
  720. $t_rep->set('status', $pn_status);
  721. $t_rep->set('access', $pn_access);
  722. if ($ps_media_path) {
  723. $t_rep->set('media', $ps_media_path, $pa_options);
  724. }
  725. if (is_array($pa_values)) {
  726. if (isset($pa_values['idno'])) {
  727. $t_rep->set('idno', $pa_values['idno']);
  728. }
  729. foreach($pa_values as $vs_element => $va_value) {
  730. if (is_array($va_value)) {
  731. // array of values (complex multi-valued attribute)
  732. $t_rep->replaceAttribute(
  733. array_merge($va_value, array(
  734. 'locale_id' => $pn_locale_id
  735. )), $vs_element);
  736. } else {
  737. // scalar value (simple single value attribute)
  738. if ($va_value) {
  739. $t_rep->replaceAttribute(array(
  740. 'locale_id' => $pn_locale_id,
  741. $vs_element => $va_value
  742. ), $vs_element);
  743. }
  744. }
  745. }
  746. }
  747. $t_rep->update();
  748. if ($t_rep->numErrors()) {
  749. $this->errors = array_merge($this->errors, $t_rep->errors());
  750. return false;
  751. }
  752. $t_oxor = new ca_objects_x_object_representations();
  753. if (!$t_oxor->load(array('object_id' => $vn_object_id, 'representation_id' => $pn_representation_id))) {
  754. $this->postError(750, _t("Representation id=%1 is not related to object id=%2", $pn_representation_id, $vn_object_id), "ca_objects->editRepresentation()");
  755. return false;
  756. } else {
  757. $t_oxor->setMode(ACCESS_WRITE);
  758. $t_oxor->set('is_primary', $pb_is_primary ? 1 : 0);
  759. if (isset($pa_options['rank']) && ($vn_rank = (int)$pa_options['rank'])) {
  760. $t_oxor->set('rank', $vn_rank);
  761. }
  762. $t_oxor->update();
  763. if ($t_oxor->numErrors()) {
  764. $this->errors = array_merge($this->errors, $t_oxor->errors());
  765. return false;
  766. }
  767. }
  768. return true;
  769. }
  770. return false;
  771. }
  772. # ------------------------------------------------------
  773. /**
  774. * Remove a single representation from the currently loaded object. Note that the representation will be removed from the database completed, so if it is also linked to other objects it will be removed from them as well.
  775. *
  776. * @param int $pn_representation_id The representation_id of the representation to remove
  777. * @return bool True if delete succeeded, false if there was an error. You can get the error messages by calling getErrors() on the ca_objects instance.
  778. */
  779. public function removeRepresentation($pn_representation_id) {
  780. if(!$this->getPrimaryKey()) { return null; }
  781. $t_rep = new ca_object_representations();
  782. if (!$t_rep->load(array('representation_id' => $pn_representation_id))) {
  783. $this->postError(750, _t("Representation id=%1 does not exist", $pn_representation_id), "ca_objects->removeRepresentation()");
  784. return false;
  785. } else {
  786. $t_rep->setMode(ACCESS_WRITE);
  787. $t_rep->delete(true);
  788. if ($t_rep->numErrors()) {
  789. $this->errors = array_merge($this->errors, $t_rep->errors());
  790. return false;
  791. }
  792. return true;
  793. }
  794. return false;
  795. }
  796. # ------------------------------------------------------
  797. /**
  798. * Removes all representations from the currently loaded object.
  799. *
  800. * @return bool True if delete succeeded, false if there was an error. You can get the error messages by calling getErrors() on the ca_objects instance.
  801. */
  802. public function removeAllRepresentations() {
  803. if (is_array($va_reps = $this->getRepresentations())) {
  804. foreach($va_reps as $vn_i => $va_rep_info) {
  805. if (!$this->removeRepresentation($va_rep_info['representation_id'])) {
  806. // Representation remove failed
  807. return false;
  808. }
  809. }
  810. }
  811. return false;
  812. }
  813. # ------------------------------------------------------
  814. #
  815. # ------------------------------------------------------
  816. /**
  817. * Return array containing information about all hierarchies, including their root_id's
  818. * For non-adhoc hierarchies such as places, this call returns the contents of the place_hierarchies list
  819. * with some extra information such as the # of top-level items in each hierarchy.
  820. *
  821. * For an ad-hoc hierarchy like that of an object, there is only ever one hierarchy to display - that of the current object.
  822. * So for adhoc hierarchies we just return a single entry corresponding to the root of the current object hierarchy
  823. */
  824. public function getHierarchyList($pb_dummy=false) {
  825. $vn_pk = $this->getPrimaryKey();
  826. if (!$vn_pk) { return null; } // have to load a row first
  827. $vs_label = $this->getLabelForDisplay(false);
  828. $vs_hier_fld = $this->getProperty('HIERARCHY_ID_FLD');
  829. $vs_parent_fld = $this->getProperty('PARENT_ID_FLD');
  830. $vn_hier_id = $this->get($vs_hier_fld);
  831. if ($this->get($vs_parent_fld)) {
  832. // currently loaded row is not the root so get the root
  833. $va_ancestors = $this->getHierarchyAncestors();
  834. if (!is_array($va_ancestors) || sizeof($va_ancestors) == 0) { return null; }
  835. $t_object = new ca_objects($va_ancestors[0]);
  836. } else {
  837. $t_object =& $this;
  838. }
  839. $va_children = $t_object->getHierarchyChildren(null, array('idsOnly' => true));
  840. $va_object_hierarchy_root = array(
  841. $t_object->get($vs_hier_fld) => array(
  842. 'object_id' => $vn_pk,
  843. 'name' => $vs_label,
  844. 'hierarchy_id' => $vn_hier_id,
  845. 'children' => sizeof($va_children)
  846. ),
  847. 'object_id' => $vn_pk,
  848. 'name' => $vs_label,
  849. 'hierarchy_id' => $vn_hier_id,
  850. 'children' => sizeof($va_children)
  851. );
  852. return $va_object_hierarchy_root;
  853. }
  854. # ------------------------------------------------------
  855. /**
  856. * Returns name of hierarchy for currently loaded row or, if specified, row identified by optional $pn_id parameter
  857. */
  858. public function getHierarchyName($pn_id=null) {
  859. if (!$pn_id) { $pn_id = $this->getPrimaryKey(); }
  860. $va_ancestors = $this->getHierarchyAncestors($pn_id, array('idsOnly' => true));
  861. if (is_array($va_ancestors) && sizeof($va_ancestors)) {
  862. $vn_parent_id = array_pop($va_ancestors);
  863. $t_object = new ca_objects($vn_parent_id);
  864. return $t_object->getLabelForDisplay(false);
  865. } else {
  866. if ($pn_id == $this->getPrimaryKey()) {
  867. return $this->getLabelForDisplay(false);
  868. } else {
  869. $t_object = new ca_objects($pn_id);
  870. return $t_object->getLabelForDisplay(false);
  871. }
  872. }
  873. }
  874. # ------------------------------------------------------------------
  875. /**
  876. * Returns associative array, keyed by primary key value with values being
  877. * the preferred label of the row from a suitable locale, ready for display
  878. *
  879. * @param array $pa_ids indexed array of primary key values to fetch labels for
  880. * @param array $pa_versions
  881. * @param array $pa_options
  882. * @return array List of media
  883. */
  884. public function getPrimaryMediaForIDs($pa_ids, $pa_versions, $pa_options = null) {
  885. if (!is_array($pa_ids) || !sizeof($pa_ids)) { return array(); }
  886. if (!is_array($pa_options)) { $pa_options = array(); }
  887. $va_access_values = $pa_options["checkAccess"];
  888. if (isset($va_access_values) && is_array($va_access_values) && sizeof($va_access_values)) {
  889. $vs_access_where = ' AND orep.access IN ('.join(',', $va_access_values).')';
  890. }
  891. $o_db = $this->getDb();
  892. $qr_res = $o_db->query("
  893. SELECT oxor.object_id, orep.media
  894. FROM ca_object_representations orep
  895. INNER JOIN ca_objects_x_object_representations AS oxor ON oxor.representation_id = orep.representation_id
  896. WHERE
  897. (oxor.object_id IN (".join(',', $pa_ids).")) AND oxor.is_primary = 1 {$vs_access_where}
  898. ");
  899. $va_media = array();
  900. while($qr_res->nextRow()) {
  901. $va_media_tags = array();
  902. foreach($pa_versions as $vs_version) {
  903. $va_media_tags['tags'][$vs_version] = $qr_res->getMediaTag('ca_object_representations.media', $vs_version);
  904. $va_media_tags['info'][$vs_version] = $qr_res->getMediaInfo('ca_object_representations.media', $vs_version);
  905. }
  906. $va_media[$qr_res->get('object_id')] = $va_media_tags;
  907. }
  908. return $va_media;
  909. }
  910. # ------------------------------------------------------
  911. /**
  912. * Returns associative array of type names
  913. */
  914. public function getTypeNamesForIDs($pa_ids) {
  915. if (!is_array($pa_ids) || !sizeof($pa_ids)) { return array(); }
  916. $o_db = $this->getDb();
  917. $ids = join(',', $pa_ids);
  918. $qr_res = $o_db->query("
  919. SELECT objects.object_id id, labels.name_singular name, labels.locale_id locale
  920. FROM ca_list_item_labels labels
  921. INNER JOIN ca_objects objects ON objects.type_id = labels.item_id
  922. WHERE (objects.object_id IN ({$ids}))
  923. ");
  924. $va_typeNames = array();
  925. while($qr_res->nextRow()) {
  926. $va_typeNames[$qr_res->get('id')] = $qr_res->get('name');
  927. }
  928. return $va_typeNames;
  929. }
  930. # ------------------------------------------------------
  931. public function getCollectionSiblings($count = 5, $type_ids = false, $pa_options = null) {
  932. if (!is_array($pa_options)) { $pa_options = array(); }
  933. if ($pa_options['checkAccess']) { $pa_options['return_with_access'] = $pa_options['checkAccess']; }
  934. $access = $pa_options['return_with_access'];
  935. $id = $this->get('ca_objects_x_collections.collection_id', array('returnAsArray' => true));
  936. $siblings = array();
  937. foreach ($id as $i) {
  938. $t_collection = new ca_collections($i);
  939. $siblings = array_merge($siblings, $t_collection->get('ca_objects_x_collections.object_id', array('returnAsArray' => true, 'checkAccess' => $access)));
  940. }
  941. foreach ($siblings as $n => $id) {
  942. // unset own id
  943. if ($id == $this->get('object_id')) {
  944. unset($siblings[$n]);
  945. }
  946. }
  947. if (count($siblings) == 0) {
  948. // return random items
  949. $ids = array_keys($this->getRandomItems(5, array('hasRepresentations' => 1, 'checkAccess' => $access)));
  950. $siblings = array();
  951. foreach ($ids as $id) {
  952. $siblings[$id] = new ca_objects($id);
  953. }
  954. $return = $siblings;
  955. } else {
  956. // return siblings
  957. if ($count > count($siblings)) { $count = count($siblings); }
  958. $rk = array_rand($siblings, $count);
  959. $t_siblings = array();
  960. foreach ($rk as $v) {
  961. $obj = new ca_objects($siblings[$v]);
  962. $t_siblings[$obj->get('object_id')] = $obj;
  963. }
  964. if ($type_ids) {
  965. $return = array('siblings' => $t_siblings, 'type_ids' => array());
  966. foreach (array_keys($t_siblings) as $id) {
  967. $return['type_ids'][$id] = $t_siblings[$id]->get('type_id');
  968. }
  969. } else {
  970. $return = $t_siblings;
  971. }
  972. }
  973. return $return;
  974. }
  975. # ------------------------------------------------------
  976. public function getIdnoSiblings($pa_options = null) {
  977. if (!is_array($pa_options)) { $pa_options = array(); }
  978. if ($pa_options['checkAccess']) { $pa_options['return_with_access'] = $pa_options['checkAccess']; }
  979. $idno = $this->get('idno');
  980. $position = strpos($idno, '/');
  981. // can we parse the idno?
  982. if ($position) {
  983. $idno = substr($idno, 0, -$position);
  984. $access = $pa_options['return_with_access'];
  985. if (sizeof($access)) {
  986. $access = implode(', ', $access);
  987. } else {
  988. $access = $this->get('access');
  989. }
  990. $o_db = $this->getDb();
  991. $qr_res = $o_db->query("
  992. SELECT o.object_id id, o.idno idno
  993. FROM ca_objects o
  994. WHERE o.idno LIKE '{$idno}%'
  995. AND o.access IN ({$access})
  996. ORDER BY o.idno
  997. ");
  998. $siblings = array();
  999. while($qr_res->nextRow()) {
  1000. $siblings[] = $qr_res->getRow();
  1001. }
  1002. $n = 0;
  1003. while (isset($siblings[$n]) && intval($siblings[$n]['id']) != $this->get('object_id')) {
  1004. $n++;
  1005. }
  1006. $next = false; $prev = false;
  1007. if (isset($siblings[$n+1])) $next = $siblings[$n+1]['id'];
  1008. if (isset($siblings[$n-1])) $prev = $siblings[$n-1]['id'];
  1009. // return 10 siblings
  1010. $objects = false;
  1011. if (sizeof($siblings) > 1) {
  1012. $objects = array();
  1013. if ($prev) $objects[] = new ca_objects($prev);
  1014. if ($next) {
  1015. $arr = array_slice($siblings, $n+1);
  1016. foreach ($arr as $key => $val) {
  1017. $arr[$key] = new ca_objects($val['id']);
  1018. }
  1019. $objects = array_slice(array_merge($objects, $arr), 0, 5);
  1020. }
  1021. }
  1022. $return = array(
  1023. 'next_id' => $next,
  1024. 'prev_id' => $prev,
  1025. 'siblings' => $objects
  1026. );
  1027. } else {
  1028. $return = false;
  1029. }
  1030. return $return;
  1031. }
  1032. # ------------------------------------------------------
  1033. public function getCollectionHierarchy($locale, $pa_options = null) {
  1034. if (!is_array($pa_options)) { $pa_options = array(); }
  1035. if ($pa_options['checkAccess']) { $pa_options['return_with_access'] = $pa_options['checkAccess']; }
  1036. $access = $pa_options['return_with_access'];
  1037. $id = $this->get('ca_objects_x_collections.collection_id', array('returnAsArray' => true, 'checkAccess' => $access));
  1038. if (sizeof($id) == 0) return false;
  1039. if (sizeof($access) == 0) return false;
  1040. $access = implode(', ', $access);
  1041. $id = $id[0];
  1042. $t_collection = new ca_collections($id);
  1043. $left = $t_collection->get('hier_left');
  1044. $hier_id = $t_collection->get('hier_collection_id');
  1045. $lang_code = $locale;
  1046. $o_db = $this->getDb();
  1047. $qr_res = $o_db->query("
  1048. SELECT cl.name AS name, parent.collection_id
  1049. FROM ca_collections AS node JOIN ca_collections AS parent
  1050. JOIN ca_collection_labels AS cl ON parent.collection_id = cl.collection_id
  1051. JOIN ca_locales AS lo ON cl.locale_id = lo.locale_id
  1052. WHERE node.hier_left BETWEEN parent.hier_left AND parent.hier_right
  1053. AND (parent.hier_collection_id = {$hier_id} AND node.hier_collection_id = {$hier_id})
  1054. AND parent.access IN ({$access})
  1055. AND lo.language = '{$lang_code}'
  1056. AND node.collection_id = {$id}
  1057. ORDER BY node.hier_left;
  1058. ");
  1059. $tree = array();
  1060. while($qr_res->nextRow()) {
  1061. $tree[] = $qr_res->getRow();
  1062. }
  1063. return $tree;
  1064. }
  1065. }
  1066. ?>

Large files files are truncated, but you can click here to view the full file