PageRenderTime 53ms CodeModel.GetById 13ms RepoModel.GetById 0ms app.codeStats 1ms

/app/models/ca_search_forms.php

https://bitbucket.org/Sinfin/pawtucket
PHP | 1351 lines | 913 code | 161 blank | 277 comment | 148 complexity | 1e14871f97ac82c1c50a546da5bfdadd 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_search_forms.php : table access class for table ca_search_forms
  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 2009-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__.'/core/ModelSettings.php');
  36. require_once(__CA_LIB_DIR__."/ca/BundlableLabelableBaseModelWithAttributes.php");
  37. require_once(__CA_MODELS_DIR__.'/ca_locales.php');
  38. require_once(__CA_MODELS_DIR__.'/ca_search_form_placements.php');
  39. require_once(__CA_MODELS_DIR__.'/ca_search_forms_x_user_groups.php');
  40. require_once(__CA_MODELS_DIR__.'/ca_metadata_elements.php');
  41. define('__CA_SEARCH_FORM_NO_ACCESS__', 0);
  42. define('__CA_SEARCH_FORM_READ_ACCESS__', 1);
  43. define('__CA_SEARCH_FORM_EDIT_ACCESS__', 2);
  44. BaseModel::$s_ca_models_definitions['ca_search_forms'] = array(
  45. 'NAME_SINGULAR' => _t('search form'),
  46. 'NAME_PLURAL' => _t('search forms'),
  47. 'FIELDS' => array(
  48. 'form_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' => 'Form id', 'DESCRIPTION' => 'Identifier for Form'
  54. ),
  55. 'user_id' => array(
  56. 'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_OMIT,
  57. 'DISPLAY_WIDTH' => 40, 'DISPLAY_HEIGHT' => 1,
  58. 'IS_NULL' => true,
  59. 'DISPLAY_FIELD' => array('ca_users.lname', 'ca_users.fname'),
  60. 'DEFAULT' => '',
  61. 'LABEL' => _t('User'), 'DESCRIPTION' => _t('The user who created the form.')
  62. ),
  63. 'form_code' => array(
  64. 'FIELD_TYPE' => FT_TEXT, 'DISPLAY_TYPE' => DT_FIELD,
  65. 'DISPLAY_WIDTH' => 22, 'DISPLAY_HEIGHT' => 1,
  66. 'IS_NULL' => true,
  67. 'DEFAULT' => '',
  68. 'LABEL' => _t('Form code'), 'DESCRIPTION' => _t('Unique code for form, used to identify the form for configuration purposes. You will need to specify this if you are using this form in a special context (on a web front-end, for example) in which the form must be unambiguously identified.'),
  69. 'BOUNDS_LENGTH' => array(0,100),
  70. 'REQUIRES' => array('is_administrator'),
  71. 'UNIQUE_WITHIN' => array()
  72. ),
  73. 'is_system' => array(
  74. 'FIELD_TYPE' => FT_BIT, 'DISPLAY_TYPE' => DT_SELECT,
  75. 'DISPLAY_WIDTH' => 10, 'DISPLAY_HEIGHT' => 1,
  76. 'IS_NULL' => false,
  77. 'DEFAULT' => '',
  78. 'LABEL' => _t('Is system form'), 'DESCRIPTION' => _t('Set this if the form is a form used by the system (as opposed to a user defined form). In general, system forms are defined by the system installer - you should not have to create system forms on your own.'),
  79. 'BOUNDS_VALUE' => array(0,1),
  80. 'REQUIRES' => array('is_administrator')
  81. ),
  82. 'table_num' => array(
  83. 'FIELD_TYPE' => FT_NUMBER, 'DISPLAY_TYPE' => DT_SELECT,
  84. 'DONT_USE_AS_BUNDLE' => true,
  85. 'DISPLAY_WIDTH' => 40, 'DISPLAY_HEIGHT' => 1,
  86. 'IS_NULL' => false,
  87. 'DEFAULT' => '',
  88. 'LABEL' => _t('Search type'), 'DESCRIPTION' => _t('Determines what type of search (objects, entities, places, etc.) the form will conduct.'),
  89. 'BOUNDS_CHOICE_LIST' => array(
  90. _t('objects') => 57,
  91. _t('object lots') => 51,
  92. _t('entities') => 20,
  93. _t('places') => 72,
  94. _t('occurrences') => 67,
  95. _t('collections') => 13,
  96. _t('storage locations') => 89,
  97. _t('loans') => 133,
  98. _t('movements') => 137,
  99. _t('tours') => 153,
  100. _t('tour stops') => 155
  101. )
  102. ),
  103. 'settings' => array(
  104. 'FIELD_TYPE' => FT_VARS, 'DISPLAY_TYPE' => DT_OMIT,
  105. 'DISPLAY_WIDTH' => 88, 'DISPLAY_HEIGHT' => 15,
  106. 'IS_NULL' => false,
  107. 'DEFAULT' => '',
  108. 'LABEL' => _t('Settings'), 'DESCRIPTION' => _t('Search form settings.')
  109. )
  110. )
  111. );
  112. global $_ca_search_forms_settings;
  113. $_ca_search_forms_settings = array( // global
  114. 'form_width' => array(
  115. 'formatType' => FT_NUMBER,
  116. 'displayType' => DT_FIELD,
  117. 'width' => 6, 'height' => 1,
  118. 'takesLocale' => false,
  119. 'default' => 3,
  120. 'label' => _t('Number of columns in form'),
  121. 'description' => _t('The number of columns wide the search will be.')
  122. )
  123. );
  124. class ca_search_forms extends BundlableLabelableBaseModelWithAttributes {
  125. # ---------------------------------
  126. # --- Object attribute properties
  127. # ---------------------------------
  128. # Describe structure of content object's properties - eg. database fields and their
  129. # associated types, what modes are supported, et al.
  130. #
  131. # ------------------------------------------------------
  132. # --- Basic object parameters
  133. # ------------------------------------------------------
  134. # what table does this class represent?
  135. protected $TABLE = 'ca_search_forms';
  136. # what is the primary key of the table?
  137. protected $PRIMARY_KEY = 'form_id';
  138. # ------------------------------------------------------
  139. # --- Properties used by standard editing scripts
  140. #
  141. # These class properties allow generic scripts to properly display
  142. # records from the table represented by this class
  143. #
  144. # ------------------------------------------------------
  145. # Array of fields to display in a listing of records from this table
  146. protected $LIST_FIELDS = array('idno');
  147. # When the list of "list fields" above contains more than one field,
  148. # the LIST_DELIMITER text is displayed between fields as a delimiter.
  149. # This is typically a comma or space, but can be any string you like
  150. protected $LIST_DELIMITER = ' ';
  151. # What you'd call a single record from this table (eg. a "person")
  152. protected $NAME_SINGULAR;
  153. # What you'd call more than one record from this table (eg. "people")
  154. protected $NAME_PLURAL;
  155. # List of fields to sort listing of records by; you can use
  156. # SQL 'ASC' and 'DESC' here if you like.
  157. protected $ORDER_BY = array('form_code');
  158. # Maximum number of record to display per page in a listing
  159. protected $MAX_RECORDS_PER_PAGE = 20;
  160. # How do you want to page through records in a listing: by number pages ordered
  161. # according to your setting above? Or alphabetically by the letters of the first
  162. # LIST_FIELD?
  163. protected $PAGE_SCHEME = 'alpha'; # alpha [alphabetical] or num [numbered pages; default]
  164. # If you want to order records arbitrarily, add a numeric field to the table and place
  165. # its name here. The generic list scripts can then use it to order table records.
  166. protected $RANK = '';
  167. # ------------------------------------------------------
  168. # Hierarchical table properties
  169. # ------------------------------------------------------
  170. protected $HIERARCHY_TYPE = null;
  171. protected $HIERARCHY_LEFT_INDEX_FLD = null;
  172. protected $HIERARCHY_RIGHT_INDEX_FLD = null;
  173. protected $HIERARCHY_PARENT_ID_FLD = null;
  174. protected $HIERARCHY_DEFINITION_TABLE = null;
  175. protected $HIERARCHY_ID_FLD = null;
  176. protected $HIERARCHY_POLY_TABLE = null;
  177. # ------------------------------------------------------
  178. # Change logging
  179. # ------------------------------------------------------
  180. protected $UNIT_ID_FIELD = null;
  181. protected $LOG_CHANGES_TO_SELF = false;
  182. protected $LOG_CHANGES_USING_AS_SUBJECT = array(
  183. "FOREIGN_KEYS" => array(
  184. ),
  185. "RELATED_TABLES" => array(
  186. )
  187. );
  188. # ------------------------------------------------------
  189. # Group-based access control
  190. # ------------------------------------------------------
  191. protected $USERS_RELATIONSHIP_TABLE = 'ca_search_forms_x_users';
  192. protected $USER_GROUPS_RELATIONSHIP_TABLE = 'ca_search_forms_x_user_groups';
  193. # ------------------------------------------------------
  194. # Labeling
  195. # ------------------------------------------------------
  196. protected $LABEL_TABLE_NAME = 'ca_search_form_labels';
  197. # ------------------------------------------------------
  198. # Attributes
  199. # ------------------------------------------------------
  200. protected $ATTRIBUTE_TYPE_ID_FLD = null; // 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
  201. protected $ATTRIBUTE_TYPE_LIST_CODE = null; // list code (ca_lists.list_code) of list defining types for this table
  202. # ------------------------------------------------------
  203. # Self-relations
  204. # ------------------------------------------------------
  205. protected $SELF_RELATION_TABLE_NAME = null;
  206. # ------------------------------------------------------
  207. # ID numbering
  208. # ------------------------------------------------------
  209. protected $ID_NUMBERING_ID_FIELD = null; // name of field containing user-defined identifier
  210. protected $ID_NUMBERING_SORT_FIELD = null; // name of field containing version of identifier for sorting (is normalized with padding to sort numbers properly)
  211. # Local config files containing specs for search elements
  212. private $opo_search_config;
  213. private $opo_search_indexing_config;
  214. # ------------------------------------------------------
  215. # $FIELDS contains information about each field in the table. The order in which the fields
  216. # are listed here is the order in which they will be returned using getFields()
  217. protected $FIELDS;
  218. # cache for haveAccessToForm()
  219. static $s_have_access_to_form_cache = array();
  220. /**
  221. * Settings delegate - implements methods for setting, getting and using 'settings' var field
  222. */
  223. public $SETTINGS;
  224. static $s_placement_list_cache; // cache for getPlacements()
  225. # ------------------------------------------------------
  226. # --- Constructor
  227. #
  228. # This is a function called when a new instance of this object is created. This
  229. # standard constructor supports three calling modes:
  230. #
  231. # 1. If called without parameters, simply creates a new, empty objects object
  232. # 2. If called with a single, valid primary key value, creates a new objects object and loads
  233. # the record identified by the primary key value
  234. #
  235. # ------------------------------------------------------
  236. public function __construct($pn_id=null) {
  237. global $_ca_search_forms_settings;
  238. // Filter list of tables form can be used for to those enabled in current config
  239. BaseModel::$s_ca_models_definitions['ca_search_forms']['FIELDS']['table_num']['BOUNDS_CHOICE_LIST'] = caFilterTableList(BaseModel::$s_ca_models_definitions['ca_search_forms']['FIELDS']['table_num']['BOUNDS_CHOICE_LIST']);
  240. parent::__construct($pn_id); # call superclass constructor
  241. $this->opo_search_config = Configuration::load($this->_CONFIG->get("search_config"));
  242. $this->opo_search_indexing_config = Configuration::load($this->opo_search_config->get("search_indexing_config"));
  243. $this->SETTINGS = new ModelSettings($this, 'settings', $_ca_search_forms_settings);
  244. }
  245. # ------------------------------------------------------
  246. public function __destruct() {
  247. unset($this->SETTINGS);
  248. }
  249. # ------------------------------------------------------
  250. public function update($pa_options=null) {
  251. if ($this->changed('table_num')) {
  252. $this->removeAllPlacements();
  253. }
  254. return parent::update($pa_options);
  255. }
  256. # ------------------------------------------------------
  257. /**
  258. * Override set() to reject changes to user_id for existing rows
  259. */
  260. public function set($pa_fields, $pm_value="", $pa_options=null) {
  261. if ($this->getPrimaryKey()) {
  262. if (is_array($pa_fields)) {
  263. if (isset($pa_fields['user_id'])) { unset($pa_fields['user_id']); }
  264. if (isset($pa_fields['table_num'])) { unset($pa_fields['table_num']); }
  265. } else {
  266. if ($pa_fields === 'user_id') { return false; }
  267. if ($pa_fields === 'table_num') { return false; }
  268. }
  269. }
  270. return parent::set($pa_fields, $pm_value, $pa_options);
  271. }
  272. # ------------------------------------------------------
  273. protected function initLabelDefinitions() {
  274. parent::initLabelDefinitions();
  275. $this->BUNDLES['ca_users'] = array('type' => 'special', 'repeating' => true, 'label' => _t('User access'));
  276. $this->BUNDLES['ca_user_groups'] = array('type' => 'special', 'repeating' => true, 'label' => _t('Group access'));
  277. $this->BUNDLES['ca_search_form_placements'] = array('type' => 'special', 'repeating' => false, 'label' => _t('Search form contents'));
  278. $this->BUNDLES['settings'] = array('type' => 'special', 'repeating' => false, 'label' => _t('Search form settings'));
  279. }
  280. # ------------------------------------------------------
  281. # Form settings
  282. # ------------------------------------------------------
  283. /**
  284. * Add bundle placement to currently loaded form
  285. *
  286. * @param string $ps_bundle_name Name of bundle to add (eg. ca_objects.idno, ca_objects.preferred_labels.name)
  287. * @param array $pa_settings Placement settings array; keys should be valid setting names
  288. * @param int $pn_rank Optional value that determines sort order of bundles in the form. If omitted, placement is added to the end of the form.
  289. * @param array $pa_options Optional array of options. Supports the following options:
  290. * user_id = if specified then add will fail if specified user does not have edit access for the form
  291. * @return int Returns placement_id of newly created placement on success, false on error
  292. */
  293. public function addPlacement($ps_bundle_name, $pa_settings, $pn_rank=null, $pa_options=null) {
  294. if (!($vn_form_id = $this->getPrimaryKey())) { return null; }
  295. unset(ca_search_forms::$s_placement_list_cache[$vn_form_id]);
  296. $pn_user_id = isset($pa_options['user_id']) ? $pa_options['user_id'] : null;
  297. if ($pn_user_id && !$this->haveAccessToForm($pn_user_id, __CA_SEARCH_FORM_EDIT_ACCESS__)) {
  298. return null;
  299. }
  300. $t_placement = new ca_search_form_placements(null, is_array($pa_options['additional_settings']) ? $pa_options['additional_settings'] : null);
  301. $t_placement->setMode(ACCESS_WRITE);
  302. $t_placement->set('form_id', $vn_form_id);
  303. $t_placement->set('bundle_name', $ps_bundle_name);
  304. $t_placement->set('rank', $pn_rank);
  305. if (is_array($pa_settings)) {
  306. foreach($pa_settings as $vs_key => $vs_value) {
  307. $t_placement->setSetting($vs_key, $vs_value);
  308. }
  309. }
  310. $t_placement->insert();
  311. if ($t_placement->numErrors()) {
  312. $this->errors = array_merge($this->errors, $t_placement->errors);
  313. return false;
  314. }
  315. return $t_placement->getPrimaryKey();
  316. }
  317. # ------------------------------------------------------
  318. /**
  319. * Removes bundle placement from form
  320. *
  321. * @param int $pn_placement_id Placement_id of placement to remove
  322. * @param array $pa_options Optional array of options. Supports the following options:
  323. * user_id = if specified then remove will fail if specified user does not have edit access for the form
  324. * @return bool Returns true on success, false on error
  325. */
  326. public function removePlacement($pn_placement_id, $pa_options=null) {
  327. if (!($vn_form_id = $this->getPrimaryKey())) { return null; }
  328. $pn_user_id = isset($pa_options['user_id']) ? $pa_options['user_id'] : null;
  329. if ($pn_user_id && !$this->haveAccessToForm($pn_user_id, __CA_SEARCH_FORM_EDIT_ACCESS__)) {
  330. return null;
  331. }
  332. $t_placement = new ca_search_form_placements($pn_placement_id);
  333. if ($t_placement->getPrimaryKey() && ($t_placement->get('form_id') == $vn_form_id)) {
  334. $t_placement->setMode(ACCESS_WRITE);
  335. $t_placement->delete(true);
  336. if ($t_placement->numErrors()) {
  337. $this->errors = array_merge($this->errors, $t_placement->errors);
  338. return false;
  339. }
  340. unset(ca_search_forms::$s_placement_list_cache[$vn_form_id]);
  341. return true;
  342. }
  343. return false;
  344. }
  345. # ------------------------------------------------------
  346. /**
  347. * Removes all bundle placements from form
  348. *
  349. * @param array $pa_options Optional array of options. Supports the following options:
  350. * user_id = if specified then remove will fail if specified user does not have edit access for the form
  351. * @return bool Returns true on success, false on error
  352. */
  353. public function removeAllPlacements($pa_options=null) {
  354. if (!($vn_form_id = $this->getPrimaryKey())) { return null; }
  355. $pn_user_id = isset($pa_options['user_id']) ? $pa_options['user_id'] : null;
  356. if ($pn_user_id && !$this->haveAccessToForm($pn_user_id, __CA_SEARCH_FORM_EDIT_ACCESS__)) {
  357. return null;
  358. }
  359. $this->getDb()->query("
  360. DELETE FROM ca_search_form_placements WHERE form_id = ?
  361. ", (int)$vn_form_id);
  362. if ($this->getDb()->numErrors()) {
  363. $this->errors = array_merge($this->errors, $this->getDb()->errors);
  364. return false;
  365. }
  366. unset(ca_search_forms::$s_placement_list_cache[$vn_form_id]);
  367. return true;
  368. }
  369. # ------------------------------------------------------
  370. /**
  371. * Returns list of placements for the currently loaded form.
  372. *
  373. * @param array $pa_options Optional array of options. Supports the following options:
  374. * noCache = if set to true then the returned list if always generated directly from the database, otherwise it is returned from the cache if possible. Set this to true if you expect the cache may be stale. Default is false.
  375. * returnAllAvailableIfEmpty = if set to true then the list of all available bundles will be returned if the currently loaded form has no placements, or if there is no form loaded
  376. * table = if using the returnAllAvailableIfEmpty option and you expect a list of available bundles to be returned if no form is loaded, you must specify the table the bundles are intended for use with with this option. Either the table name or number may be used.
  377. * user_id = if specified then placements are only returned if the user has at least read access to the form
  378. * @return array List of placements in display order. Array is keyed on bundle name. Values are arrays with the following keys:
  379. * placement_id = primary key of ca_search_form_placements row - a unique id for the placement
  380. * bundle_name = bundle name (a code - not for form)
  381. * settings = array of placement settings. Keys are setting names.
  382. * form = form string for bundle
  383. */
  384. public function getPlacements($pa_options=null) {
  385. $pb_no_cache = (isset($pa_options['noCache'])) ? (bool)$pa_options['noCache'] : false;
  386. $pb_settings_only = (isset($pa_options['settingsOnly'])) ? (bool)$pa_options['settingsOnly'] : false;
  387. $pb_return_all_available_if_empty = (isset($pa_options['returnAllAvailableIfEmpty']) && !$pb_settings_only) ? (bool)$pa_options['returnAllAvailableIfEmpty'] : false;
  388. $ps_table = (isset($pa_options['table'])) ? $pa_options['table'] : null;
  389. $pn_user_id = isset($pa_options['user_id']) ? $pa_options['user_id'] : null;
  390. if ($pn_user_id && !$this->haveAccessToForm($pn_user_id, __ca_search_form_READ_ACCESS__)) {
  391. return array();
  392. }
  393. if (!($vn_form_id = $this->getPrimaryKey())) {
  394. if ($pb_return_all_available_if_empty && $ps_table) {
  395. return ca_search_forms::$s_placement_list_cache[$vn_form_id] = $this->getAvailableBundles($ps_table);
  396. }
  397. return array();
  398. }
  399. if (!$pb_no_cache && isset(ca_search_forms::$s_placement_list_cache[$vn_form_id]) && ca_search_forms::$s_placement_list_cache[$vn_form_id]) {
  400. return ca_search_forms::$s_placement_list_cache[$vn_form_id];
  401. }
  402. $o_db = $this->getDb();
  403. $qr_res = $o_db->query("
  404. SELECT placement_id, bundle_name, settings
  405. FROM ca_search_form_placements
  406. WHERE
  407. form_id = ?
  408. ORDER BY rank
  409. ", (int)$vn_form_id);
  410. $va_available_bundles = ($pb_settings_only) ? array() : $this->getAvailableBundles();
  411. $va_placements = array();
  412. if ($qr_res->numRows() > 0) {
  413. $t_placement = new ca_search_form_placements();
  414. while($qr_res->nextRow()) {
  415. $vs_bundle_name = $qr_res->get('bundle_name');
  416. $va_placements[$vn_placement_id = (int)$qr_res->get('placement_id')] = $qr_res->getRow();
  417. $va_placements[$vn_placement_id]['settings'] = $va_settings = caUnserializeForDatabase($qr_res->get('settings'));
  418. if (!$pb_settings_only) {
  419. $t_placement->setSettingDefinitionsForPlacement($va_available_bundles[$vs_bundle_name]['settings']);
  420. $va_placements[$vn_placement_id]['form'] = $va_available_bundles[$vs_bundle_name]['form'];
  421. $va_placements[$vn_placement_id]['settingsForm'] = $t_placement->getHTMLSettingForm(array('id' => $vs_bundle_name.'_'.$vn_placement_id, 'settings' => $va_settings));
  422. }
  423. }
  424. } else {
  425. if ($pb_return_all_available_if_empty) {
  426. $va_placements = $this->getAvailableBundles($this->get('table_num'));
  427. }
  428. }
  429. ca_search_forms::$s_placement_list_cache[$vn_form_id] = $va_placements;
  430. return $va_placements;
  431. }
  432. # ------------------------------------------------------
  433. /**
  434. * Returns list of search forms subject to options
  435. *
  436. * @param array $pa_options Optional array of options. Supported options are:
  437. * table - if set, list is restricted to forms that pertain to the specified table. You can pass a table name or number. If omitted forms for all tables will be returned.
  438. * user_id - Restricts returned forms to those accessible by the current user. If omitted then all forms, regardless of access are returned.
  439. * access - Restricts returned forms to those with at least the specified access level for the specified user. If user_id is omitted then this option has no effect. If user_id is set and this option is omitted, then forms where the user has at least read access will be returned.
  440. * @return array Array of forms keyed on form_id and then locale_id. Keys for the per-locale value array include: form_id, form_code, user_id, table_num, label_id, name (display name of form), locale_id (locale of form name), search_form_content_type (display name of content this form searches on)
  441. */
  442. public function getForms($pa_options=null) {
  443. if (!is_array($pa_options)) { $pa_options = array(); }
  444. $pm_table_name_or_num = isset($pa_options['table']) ? $pa_options['table'] : null;
  445. $pn_user_id = isset($pa_options['user_id']) ? $pa_options['user_id'] : null;
  446. $pn_access = isset($pa_options['access']) ? $pa_options['access'] : null;
  447. $o_dm = $this->getAppDatamodel();
  448. if ($pm_table_name_or_num && !($vn_table_num = $o_dm->getTableNum($pm_table_name_or_num))) { return array(); }
  449. $o_db = $this->getDb();
  450. $va_sql_wheres = array('((sfl.is_preferred = 1) or (sfl.is_preferred is null))');
  451. if ($vn_table_num > 0) {
  452. $va_sql_wheres[] = "(sf.table_num = ".intval($vn_table_num).")";
  453. }
  454. $va_sql_access_wheres = array();
  455. if ($pn_user_id) {
  456. $o_dm = $this->getAppDatamodel();
  457. $t_user = $o_dm->getInstanceByTableName('ca_users', true);
  458. $t_user->load($pn_user_id);
  459. if ($t_user->getPrimaryKey()) {
  460. $vs_access_sql = ($pn_access > 0) ? " AND (access >= ".intval($pn_access).")" : "";
  461. if (is_array($va_groups = $t_user->getUserGroups()) && sizeof($va_groups)) {
  462. $vs_sql = "(
  463. (sf.user_id = ".intval($pn_user_id).") OR
  464. (sf.form_id IN (
  465. SELECT form_id
  466. FROM ca_search_forms_x_user_groups
  467. WHERE
  468. group_id IN (".join(',', array_keys($va_groups)).") {$vs_access_sql}
  469. )
  470. )
  471. )";
  472. } else {
  473. $vs_sql = "(sf.user_id = {$pn_user_id})";
  474. }
  475. $vs_sql .= " OR (sf.form_id IN (
  476. SELECT form_id
  477. FROM ca_search_forms_x_users
  478. WHERE
  479. user_id = {$pn_user_id} {$vs_access_sql}
  480. )
  481. )";
  482. $va_sql_access_wheres[] = "({$vs_sql})";
  483. }
  484. }
  485. if ($pn_access == __CA_SEARCH_FORM_READ_ACCESS__) {
  486. $va_sql_access_wheres[] = "(sf.is_system = 1)";
  487. }
  488. if (sizeof($va_sql_access_wheres)) {
  489. $va_sql_wheres[] = "(".join(" OR ", $va_sql_access_wheres).")";
  490. }
  491. // get forms
  492. $qr_res = $o_db->query($vs_sql = "
  493. SELECT
  494. sf.form_id, sf.form_code, sf.user_id, sf.table_num,
  495. sfl.label_id, sfl.name, sfl.locale_id, u.fname, u.lname, u.email,
  496. l.language, l.country
  497. FROM ca_search_forms sf
  498. LEFT JOIN ca_search_form_labels AS sfl ON sf.form_id = sfl.form_id
  499. LEFT JOIN ca_locales AS l ON sfl.locale_id = l.locale_id
  500. INNER JOIN ca_users AS u ON sf.user_id = u.user_id
  501. ".(sizeof($va_sql_wheres) ? 'WHERE ' : '')."
  502. ".join(' AND ', $va_sql_wheres)."
  503. ");
  504. $va_displays = array();
  505. $t_list = new ca_lists();
  506. $va_type_name_cache = array();
  507. while($qr_res->nextRow()) {
  508. $vn_table_num = $qr_res->get('table_num');
  509. if (!isset($va_type_name_cache[$vn_table_num]) || !($vs_display_type = $va_type_name_cache[$vn_table_num])) {
  510. $vs_display_type = $va_type_name_cache[$vn_table_num] = $this->getFormTypeName($vn_table_num, array('number' => 'plural'));
  511. }
  512. $va_displays[$qr_res->get('form_id')][$qr_res->get('locale_id')] = array_merge($qr_res->getRow(), array('search_form_content_type' => $vs_display_type));
  513. }
  514. return $va_displays;
  515. }
  516. # ------------------------------------------------------
  517. /**
  518. * Returns number of forms conforming to specification in options
  519. *
  520. * @param array $pa_options Optional array of options. Supported options are:
  521. * table - if set, list is restricted to forms that pertain to the specified table. You can pass a table name or number. If omitted forms for all tables will be returned.
  522. * user_id - Restricts returned forms to those accessible by the current user. If omitted then all forms, regardless of access are returned.
  523. * access - Restricts returned forms to those with at least the specified access level for the specified user. If user_id is omitted then this option has no effect. If user_id is set and this option is omitted, then forms where the user has at least read access will be returned.
  524. * @return int Number of forms available
  525. */
  526. public function getFormCount($pa_options=null) {
  527. if (!is_array($pa_options)) { $pa_options = array(); }
  528. $va_forms = $this->getForms($pa_options);
  529. if (is_array($va_forms)) { return sizeof($va_forms); } else { return 0; }
  530. }
  531. # ------------------------------------------------------
  532. /**
  533. * Return available search forms as HTML <select> drop-down menu
  534. *
  535. * @param string $ps_select_name Name attribute for <select> form element
  536. * @param array $pa_attributes Optional array of attributes to embed in HTML <select> tag. Keys are attribute names and values are attribute values.
  537. * @param array $pa_options Optional array of options. Supported options include:
  538. * Supports all options supported by caHTMLSelect() and ca_search_forms::getForms() + the following:
  539. * addDefaultForm - if true, the "default" form is included at the head of the list; this is simply a form called "default" that is assumed to be handled by your code; the default is not to add the default value (false)
  540. * addDefaultFormIfEmpty - same as 'addDefaultForm' except that the default value is only added if the form list is empty
  541. * @return string HTML code defining <select> drop-down
  542. */
  543. public function getFormsAsHTMLSelect($ps_select_name, $pa_attributes=null, $pa_options=null) {
  544. if (!is_array($pa_options)) { $pa_options = array(); }
  545. $va_available_forms = caExtractValuesByUserLocale($this->getForms($pa_options));
  546. $va_content = array();
  547. if (
  548. (isset($pa_options['addDefaultForm']) && $pa_options['addDefaultForm'])
  549. ||
  550. (isset($pa_options['addDefaultFormIfEmpty']) && ($pa_options['addDefaultFormIfEmpty']) && (!sizeof($va_available_forms)))
  551. ) {
  552. $va_content[_t('Default')] = 0;
  553. }
  554. foreach($va_available_forms as $vn_form_id => $va_info) {
  555. $va_content[$va_info['name']] = $vn_form_id;
  556. }
  557. if (sizeof($va_content) == 0) { return ''; }
  558. return caHTMLSelect($ps_select_name, $va_content, $pa_attributes, $pa_options);
  559. }
  560. # ------------------------------------------------------
  561. /**
  562. * Returns name of type of content (synonymous with the table name for the content) currently loaded form searches on. Will return name in singular number unless the 'number' option is set to 'plural'
  563. *
  564. * @param int $pn_table_num Table number to return name for. If omitted then the name for the content type search on by the current form will be returned. Use this parameter if you want to force a content type without having to load a form.
  565. * @param array $pa_options Optional array of options. Supported options are:
  566. * number = Set to 'plural' to return plural version of name; set to 'singular' [default] to return the singular version
  567. * @return string The name of the type of content or null if $pn_table_num is not set to a valid table and no form is loaded.
  568. */
  569. public function getFormTypeName($pm_table_name_or_num=null, $pa_options=null) {
  570. $o_dm = $this->getAppDatamodel();
  571. if (!$pm_table_name_or_num && !($pm_table_name_or_num = $this->get('table_num'))) { return null; }
  572. if (!($vn_table_num = $o_dm->getTableNum($pm_table_name_or_num))) { return null; }
  573. $t_instance = $o_dm->getInstanceByTableNum($vn_table_num, true);
  574. return (isset($pa_options['number']) && ($pa_options['number'] == 'plural')) ? $t_instance->getProperty('NAME_PLURAL') : $t_instance->getProperty('NAME_SINGULAR');
  575. }
  576. # ------------------------------------------------------
  577. /**
  578. * Determines if user has access to a form at a specified access level.
  579. *
  580. * @param int $pn_user_id user_id of user to check form access for
  581. * @param int $pn_access type of access required. Use __CA_SEARCH_FORM_READ_ACCESS__ for read-only access or __CA_SEARCH_FORM_EDIT_ACCESS__ for editing (full) access
  582. * @param int $pn_form_id The id of the form to check. If omitted then currently loaded form will be checked.
  583. * @return bool True if user has access, false if not
  584. */
  585. public function haveAccessToForm($pn_user_id, $pn_access, $pn_form_id=null) {
  586. if ($pn_form_id) {
  587. $vn_form_id = $pn_form_id;
  588. $t_form = new ca_search_forms($vn_form_id);
  589. $vn_form_user_id = $t_form->get('user_id');
  590. } else {
  591. $vn_form_user_id = $this->get('user_id');
  592. $t_form = $this;
  593. }
  594. if(!$vn_form_id && !($vn_form_id = $t_form->getPrimaryKey())) {
  595. return true; // new form
  596. }
  597. if (isset(ca_search_forms::$s_have_access_to_form_cache[$vn_form_id.'/'.$pn_user_id.'/'.$pn_access])) {
  598. return ca_search_forms::$s_have_access_to_form_cache[$vn_form_id.'/'.$pn_user_id.'/'.$pn_access];
  599. }
  600. if (($vn_form_user_id == $pn_user_id)) { // owners have all access
  601. return ca_search_forms::$s_have_access_to_form_cache[$vn_form_id.'/'.$pn_user_id.'/'.$pn_access] = true;
  602. }
  603. if ((bool)$t_form->get('is_system') && ($pn_access == __CA_SEARCH_FORM_READ_ACCESS__)) { // system forms are readable by all
  604. return ca_search_forms::$s_have_access_to_form_cache[$vn_form_id.'/'.$pn_user_id.'/'.$pn_access] = true;
  605. }
  606. $o_db = $this->getDb();
  607. $qr_res = $o_db->query("
  608. SELECT fxg.form_id
  609. FROM ca_search_forms_x_user_groups fxg
  610. INNER JOIN ca_user_groups AS ug ON fxg.group_id = ug.group_id
  611. INNER JOIN ca_users_x_groups AS uxg ON uxg.group_id = ug.group_id
  612. WHERE
  613. (fxg.access >= ?) AND (uxg.user_id = ?) AND (fxg.form_id = ?)
  614. ", (int)$pn_access, (int)$pn_user_id, (int)$vn_form_id);
  615. if ($qr_res->numRows() > 0) { return ca_search_forms::$s_have_access_to_form_cache[$vn_form_id.'/'.$pn_user_id.'/'.$pn_access] = true; }
  616. $qr_res = $o_db->query("
  617. SELECT fxu.form_id
  618. FROM ca_search_forms_x_users fxu
  619. INNER JOIN ca_users AS u ON fxu.user_id = u.user_id
  620. WHERE
  621. (fxu.access >= ?) AND (u.user_id = ?) AND (fxu.form_id = ?)
  622. ", (int)$pn_access, (int)$pn_user_id, (int)$vn_form_id);
  623. if ($qr_res->numRows() > 0) { return ca_search_forms::$s_have_access_to_form_cache[$vn_form_id.'/'.$pn_user_id.'/'.$pn_access] = true; }
  624. return ca_search_forms::$s_have_access_to_form_cache[$vn_form_id.'/'.$pn_user_id.'/'.$pn_access] = false;
  625. }
  626. # ------------------------------------------------------
  627. # Settings
  628. # ------------------------------------------------------
  629. /**
  630. * Reroutes calls to method implemented by settings delegate to the delegate class
  631. */
  632. public function __call($ps_name, $pa_arguments) {
  633. if (method_exists($this->SETTINGS, $ps_name)) {
  634. return call_user_func_array(array($this->SETTINGS, $ps_name), $pa_arguments);
  635. }
  636. die($this->tableName()." does not implement method {$ps_name}");
  637. }
  638. # ------------------------------------------------------
  639. # Support methods for search form setup UI
  640. # ------------------------------------------------------
  641. /**
  642. * Returns all available search form placements - those data bundles that can be searches for the given content type, in other words.
  643. * The returned value is a list of arrays; each array contains a 'bundle' specifier than can be passed got Model::get() or SearchResult::get() and a display name
  644. *
  645. * @param mixed $pm_table_name_or_num The table name or number specifying the content type to fetch bundles for. If omitted the content table of the currently loaded search form will be used.
  646. * @return array And array of bundles keyed on display label. Each value is an array with these keys:
  647. * bundle = The bundle name (eg. ca_objects.idno)
  648. * display = Display label for each available bundle
  649. * description = Description of bundle
  650. *
  651. * Will return null if table name or number is invalid.
  652. */
  653. public function getAvailableBundles($pm_table_name_or_num=null, $pa_options=null) {
  654. if (!$pm_table_name_or_num) { $pm_table_name_or_num = $this->get('table_num'); }
  655. $pm_table_name_or_num = $this->_DATAMODEL->getTableNum($pm_table_name_or_num);
  656. if (!$pm_table_name_or_num) { return null; }
  657. $t_instance = $this->_DATAMODEL->getInstanceByTableNum($pm_table_name_or_num, true);
  658. $va_search_settings = $this->opo_search_indexing_config->getAssoc($this->_DATAMODEL->getTableName($pm_table_name_or_num));
  659. $vs_primary_table = $t_instance->tableName();
  660. $vs_table_display_name = $t_instance->getProperty('NAME_PLURAL');
  661. $t_placement = new ca_search_form_placements(null, array());
  662. $va_available_bundles = array();
  663. $va_additional_settings = array(
  664. 'width' => array(
  665. 'formatType' => FT_TEXT,
  666. 'displayType' => DT_FIELD,
  667. 'width' => 4, 'height' => 1,
  668. 'takesLocale' => false,
  669. 'default' => "100px",
  670. 'label' => _t('Width'),
  671. 'description' => _t('Width, in characters, of search form elements.')
  672. )
  673. );
  674. $t_placement->setSettingDefinitionsForPlacement($va_additional_settings);
  675. // Full-text
  676. $vs_bundle = "_fulltext";
  677. $vs_display = "<div id='searchFormEditor__fulltext'><span class='bundleDisplayEditorPlacementListItemTitle'>"._t("General").'</span> '.($vs_label = _t('Full text'))."</div>";
  678. $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array(
  679. 'bundle' => $vs_bundle,
  680. 'label' => $vs_label,
  681. 'display' => $vs_display,
  682. 'description' => $vs_description = _t('Searches on all content that has been indexed'),
  683. 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle.'_0')),
  684. 'settings' => $va_additional_settings
  685. );
  686. TooltipManager::add(
  687. "#searchFormEditor__fulltext",
  688. "<h2>{$vs_label}</h2>{$vs_description}"
  689. );
  690. // get fields
  691. foreach($va_search_settings as $vs_table => $va_fields) {
  692. if (!is_array($va_fields['fields'])) { continue; }
  693. if ($vs_table == $vs_primary_table) {
  694. $va_element_codes = (method_exists($t_instance, 'getApplicableElementCodes') ? $t_instance->getApplicableElementCodes(null, false, false) : array());
  695. $va_field_list = array();
  696. foreach($va_fields['fields'] as $vs_field => $va_field_indexing_info) {
  697. if ($vs_field === '_metadata') {
  698. foreach($va_element_codes as $vs_code) {
  699. $va_field_list[$vs_code] = array();
  700. }
  701. } else {
  702. $va_field_list[$vs_field] = $va_field_indexing_info;
  703. }
  704. }
  705. foreach($va_field_list as $vs_field => $va_field_indexing_info) {
  706. if (in_array('DONT_INCLUDE_IN_SEARCH_FORM', $va_field_indexing_info)) { continue; }
  707. if (!($va_field_info = $t_instance->getFieldInfo($vs_field))) {
  708. // is it an attribute?
  709. if (in_array($vs_field, $va_element_codes)) {
  710. $t_element = $this->_getElementInstance($vs_field);
  711. if (in_array($t_element->get('datatype'), array(15, 16))) { continue; } // skip file and media attributes - never searchable
  712. if (!$t_element->getSetting('canBeUsedInSearchForm')) { continue; }
  713. $vs_bundle = $vs_table.'.'.$vs_field;
  714. $vs_display = "<div id='searchFormEditor_{$vs_table}_{$vs_field}'><span class='bundleDisplayEditorPlacementListItemTitle'>".caUcFirstUTF8Safe($t_instance->getProperty('NAME_SINGULAR'))."</span> ".($vs_label = $t_instance->getDisplayLabel($vs_bundle))."</div>";
  715. $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array(
  716. 'bundle' => $vs_bundle,
  717. 'label' => $vs_label,
  718. 'display' => $vs_display,
  719. 'description' => $vs_description = $t_instance->getDisplayDescription($vs_bundle),
  720. 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle.'_0')),
  721. 'settings' => $va_additional_settings
  722. );
  723. TooltipManager::add(
  724. "#searchFormEditor_{$vs_table}_{$vs_field}",
  725. "<h2>{$vs_label}</h2>{$vs_description}"
  726. );
  727. }
  728. } else {
  729. if (isset($va_field_info['DONT_USE_AS_BUNDLE']) && $va_field_info['DONT_USE_AS_BUNDLE']) { continue; }
  730. if (in_array($va_field_info['FIELD_TYPE'], array(FT_MEDIA, FT_FILE))) { continue; }
  731. $vs_bundle = $vs_table.'.'.$vs_field;
  732. $vs_display = "<div id='searchFormEditor_{$vs_table}_{$vs_field}'><span class='bundleDisplayEditorPlacementListItemTitle'>".caUcFirstUTF8Safe($t_instance->getProperty('NAME_SINGULAR'))."</span> ".($vs_label = $t_instance->getDisplayLabel($vs_bundle))."</div>";
  733. $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array(
  734. 'bundle' => $vs_bundle,
  735. 'label' => $vs_label,
  736. 'display' => $vs_display,
  737. 'description' => $vs_description = $t_instance->getDisplayDescription($vs_bundle),
  738. 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle.'_0')),
  739. 'settings' => $va_additional_settings
  740. );
  741. TooltipManager::add(
  742. "#searchFormEditor_{$vs_table}_{$vs_field}",
  743. "<h2>{$vs_label}</h2>{$vs_description}"
  744. );
  745. }
  746. }
  747. } else {
  748. // related table
  749. if ($this->getAppConfig()->get($vs_table.'_disable')) { continue; }
  750. $t_table = $this->_DATAMODEL->getInstanceByTableName($vs_table, true);
  751. if ((method_exists($t_table, "getSubjectTableName") && $vs_subject_table = $t_table->getSubjectTableName())) {
  752. if ($this->getAppConfig()->get($vs_subject_table.'_disable')) { continue; }
  753. }
  754. foreach($va_fields['fields'] as $vs_field => $va_field_indexing_info) {
  755. if (in_array('DONT_INCLUDE_IN_SEARCH_FORM', $va_field_indexing_info)) { continue; }
  756. if (($va_field_info = $t_table->getFieldInfo($vs_field))) {
  757. if (isset($va_field_info['DONT_USE_AS_BUNDLE']) && $va_field_info['DONT_USE_AS_BUNDLE']) { continue; }
  758. $vs_bundle = $vs_table.'.'.$vs_field;
  759. $vs_related_table = caUcFirstUTF8Safe($t_table->getProperty('NAME_SINGULAR'));
  760. if (method_exists($t_table, 'getSubjectTableInstance')) {
  761. $t_subject = $t_table->getSubjectTableInstance();
  762. $vs_related_table = caUcFirstUTF8Safe($t_subject->getProperty('NAME_SINGULAR'));
  763. }
  764. $vs_label = $t_instance->getDisplayLabel($vs_bundle);
  765. if (method_exists($t_table, "getSubjectTableName") && ($vs_primary_table == $vs_subject_table)) {
  766. $vs_display = "<div id='searchFormEditor_{$vs_table}_{$vs_field}'><span class='bundleDisplayEditorPlacementListItemTitle'>".caUcFirstUTF8Safe($t_subject->getProperty('NAME_SINGULAR'))."</span> {$vs_label}</div>";
  767. } else {
  768. $vs_display = "<div id='searchFormEditor_{$vs_table}_{$vs_field}'><span class='bundleDisplayEditorPlacementListItemTitle'>{$vs_related_table}</span> {$vs_label}</div>";
  769. }
  770. $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array(
  771. 'bundle' => $vs_bundle,
  772. 'label' => $vs_label,
  773. 'display' => $vs_display,
  774. 'description' => $vs_description = $t_instance->getDisplayDescription($vs_bundle),
  775. 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle.'_0')),
  776. 'settings' => $va_additional_settings
  777. );
  778. TooltipManager::add(
  779. "#searchFormEditor_{$vs_table}_{$vs_field}",
  780. "<h2>{$vs_label}</h2>{$vs_description}"
  781. );
  782. }
  783. }
  784. }
  785. }
  786. //
  787. // access points
  788. //
  789. $va_access_points = (isset($va_search_settings['_access_points']) && is_array($va_search_settings['_access_points'])) ? $va_search_settings['_access_points'] : array();
  790. //unset($va_search_settings['_access_points']);
  791. foreach($va_access_points as $vs_access_point => $va_access_point_info) {
  792. if (isset($va_access_point_info['options']) && is_array($va_access_point_info['options'])) {
  793. if (in_array('DONT_INCLUDE_IN_SEARCH_FORM', $va_access_point_info['options'])) { continue; }
  794. }
  795. $vs_display = "<div id='searchFormEditor_{$vs_access_point}'><span class='bundleDisplayEditorPlacementListItemTitle'>"._t('Access point').'</span> '.($vs_label = ((isset($va_access_point_info['name']) && $va_access_point_info['name']) ? $va_access_point_info['name'] : $vs_access_point))."</div>";
  796. $va_available_bundles[strip_tags($vs_display)][$vs_access_point] = array(
  797. 'bundle' => $vs_access_point,
  798. 'label' => $vs_label,
  799. 'display' => $vs_display,
  800. 'description' => $vs_description = ((isset($va_access_point_info['description']) && $va_access_point_info['description']) ? $va_access_point_info['description'] : ''),
  801. 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_access_point.'_0')),
  802. 'settings' => $va_additional_settings
  803. );
  804. TooltipManager::add(
  805. "#searchFormEditor_{$vs_access_point}",
  806. "<h2>{$vs_label}</h2>{$vs_description}"
  807. );
  808. }
  809. //
  810. // created and modified
  811. //
  812. $t_placement->setSettingDefinitionsForPlacement($va_additional_settings);
  813. foreach(array('created', 'modified') as $vs_bundle) {
  814. $vs_display = "<div id='searchFormEditor_{$vs_bundle}'><span class='bundleDisplayEditorPlacementListItemTitle'>"._t('General')."</span> ".($vs_label = $t_instance->getDisplayLabel($vs_bundle))."</div>";
  815. $va_available_bundles[strip_tags($vs_display)][$vs_bundle] = array(
  816. 'bundle' => $vs_bundle,
  817. 'label' => $vs_label,
  818. 'display' => $vs_display,
  819. 'description' => $vs_description = $t_instance->getDisplayDescription($vs_bundle),
  820. 'settingsForm' => $t_placement->getHTMLSettingForm(array('id' => $vs_bundle.'_0')),
  821. 'settings' => $va_additional_settings
  822. );
  823. TooltipManager::add(
  824. "#searchFormEditor_{$vs_bundle}",
  825. "<h2>{$vs_label}</h2>{$vs_description}"
  826. );
  827. }
  828. ksort($va_available_bundles);
  829. $va_sorted_bundles = array();
  830. foreach($va_available_bundles as $vs_k => $va_val) {
  831. foreach($va_val as $vs_real_key => $va_info) {
  832. $va_sorted_bundles[$vs_real_key] = $va_info;
  833. }
  834. }
  835. return $va_sorted_bundles;
  836. }
  837. # ------------------------------------------------------
  838. /**
  839. * Returns list of placements in the currently loaded display
  840. *
  841. * @param array $pa_options Optional array of options. Supported options are:
  842. * noCache = if set to true, no caching of placement values is performed.
  843. * user_id = if specified then placements are only returned if the user has at least read access to the display
  844. * @return array List of placements. Each element in the list is an array with the following keys:
  845. * display = A display label for the bundle
  846. * bundle = The bundle name
  847. */
  848. public function getPlacementsInForm($pa_options=null) {
  849. if (!is_array($pa_options)) { $pa_options = array(); }
  850. $pb_no_cache = isset($pa_options['noCache']) ? (bool)$pa_options['noCache'] : false;
  851. $pn_user_id = isset($pa_options['user_id']) ? $pa_options['user_id'] : null;
  852. if ($pn_user_id && !$this->haveAccessToForm($pn_user_id, __CA_SEARCH_FORM_READ_ACCESS__)) {
  853. return array();
  854. }
  855. if (!($pn_table_num = $this->_DATAMODEL->getTableNum($this->get('table_num')))) { return null; }
  856. $t_instance = $this->_DATAMODEL->getInstanceByTableNum($pn_table_num, true);
  857. if(!is_array($va_placements = $this->getPlacements($pa_options))) { $va_placements = array(); }
  858. $va_available_bundles = $this->getAvailableBundles($pn_table_num);
  859. $va_placements_in_form = array();
  860. foreach($va_placements as $vn_placement_id => $va_placement) {
  861. $vs_label = $va_available_bundles[$va_placement['bundle_name']]['label'];
  862. $vs_display = $va_available_bundles[$va_placement['bundle_name']]['display'];
  863. if(is_array($va_placement['settings']['label'])){
  864. if ($vs_user_set_label = array_shift(caExtractValuesByUserLocale(array($va_placement['settings']['label'])))) {
  865. $vs_label = "{$vs_label} (<em>{$vs_user_set_label}</em>)";
  866. $vs_display = "{$vs_display} (<em>{$vs_user_set_label}</em>)";
  867. }
  868. }
  869. $va_placement['display'] = $vs_display = preg_replace("!<div id='searchFormEditor_[^']+!", "<div id='searchFormEditorSelected_{$vn_placement_id}", $vs_display);
  870. $va_placement['bundle'] = $va_placement['bundle_name']; // we used 'bundle' in the arrays, but the database field is called 'bundle_name' and getPlacements() returns data directly from the database
  871. unset($va_placement['bundle_name']);
  872. $va_placements_in_form[$vn_placement_id] = $va_placement;
  873. $vs_description = $t_instance->getDisplayDescription($va_placement['bundle']);
  874. TooltipManager::add(
  875. "#searchFormEditorSelected_{$vn_placement_id}",
  876. "<h2>{$vs_label}</h2>{$vs_description}"
  877. );
  878. }
  879. return $va_placements_in_form;
  880. }
  881. # ------------------------------------------------------
  882. /**
  883. * Returns number of placements in the currently loaded search form
  884. *
  885. * @param array $pa_options Optional array of options. Supported options are:
  886. * noCache = if set to true, no caching of placement values is performed.
  887. * user_id = if specified then placements are only returned if the user has at least read access to the form
  888. * @return int Number of placements.
  889. */
  890. public function getPlacementCount($pa_options=null) {
  891. return sizeof($this->getPlacementsInForm($pa_options));
  892. }
  893. # ------------------------------------------------------
  894. #
  895. # ------------------------------------------------------
  896. #
  897. # Search form processing
  898. #
  899. # ------------------------------------------------------
  900. # Form renderer
  901. # ------------------------------------------------------
  902. /**
  903. * Render currently loaded form as HTML
  904. */
  905. public function getHTMLFormElements($po_request, $pa_form_data=null) {
  906. if (!$this->getPrimaryKey()) { return null; }
  907. if (!is_array($pa_form_data)) { $pa_form_data = array(); }
  908. foreach($pa_form_data as $vs_k => $vs_v) {
  909. $pa_form_data[$vs_k] = trim($pa_form_data[$vs_k]);
  910. }
  911. $va_form_contents = $this->getPlacements();
  912. $o_dm = Datamodel::load();
  913. $va_output = array();
  914. if (!($vs_form_table_name = $o_dm->getTableName($this->get('table_num')))) { return null; }
  915. $t_subject = $o_dm->getInstanceByTableName($vs_form_table_name, true);
  916. foreach($va_form_contents as $vn_i => $va_element) {
  917. $vs_field_label = '';
  918. if (is_array($va_element['settings']['label']) && (sizeof($va_element['settings']['label']) > 0)) {
  919. if ((is_array($va_field_labels = caExtractValuesByUserLocale(array($va_element['settings']['label']))) && sizeof($va_field_labels) > 0)) {
  920. $vs_field_label = array_shift($va_field_labels);
  921. }
  922. }
  923. switch($va_element['bundle_name']) {
  924. case '_fulltext':
  925. if (!$vs_field_label) { $vs_field_label = _t('Full text'); }
  926. $va_output[] = array(
  927. 'element' => caHTMLTextInput("_fulltext", array(
  928. 'value' => $pa_form_data["_fulltext"],
  929. 'id' => "_fulltext"
  930. ),
  931. array(
  932. 'width' => (isset($va_element['settings']['width']) && ($va_element['settings']['width'] > 0)) ? $va_element['settings']['width'] : "100px",
  933. 'height' => (isset($va_element['settings']['height']) && ($va_element['settings']['height'] > 0)) ? $va_element['settings']['height'] : 1
  934. )),
  935. 'label' => $vs_field_label,
  936. 'name' => $vs_field
  937. );
  938. continue(2);
  939. case 'created':
  940. case 'modified':
  941. $va_output[] = array(
  942. 'element' => $t_subject->htmlFormElementForSearch($po_request, $va_element['bundle_name'], array(
  943. 'values' => $pa_form_data,
  944. 'width' => (isset($va_element['settings']['width']) && ($va_element['settings']['width'] > 0)) ? $va_element['settings']['width'] : "100px",
  945. 'height' => (isset($va_element['settings']['height']) && ($va_element['settings']['height'] > 0)) ? $va_element['settings']['height'] : 1,
  946. 'format' => '^ELEMENT',
  947. 'multivalueFormat' => '<i>^LABEL</i><br/>^ELEMENT',
  948. 'id' => str_replace('.', '_', $va_element['bundle_name'])
  949. )),
  950. 'label' => ($vs_field_label) ? $vs_field_label : $t_subject->getDisplayLabel($va_element['bundle_name']),
  951. 'name' => $va_element['bundle_name']
  952. );
  953. continue(2);
  954. }
  955. $va_tmp = explode('.', $vs_field = $va_element['bundle_name']);
  956. if (!($t_instance = $o_dm->getInstanceByTableName($va_tmp[0], true))) {
  957. // is this an access point?
  958. $va_search_settings = $this->opo_se

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