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

/lib/core/Search/ContentSource/TrackerItemSource.php

https://gitlab.com/ElvisAns/tiki
PHP | 262 lines | 197 code | 54 blank | 11 comment | 21 complexity | 7d82252a55fd0d0116e46200fc35558b MD5 | raw file
  1. <?php
  2. // (c) Copyright by authors of the Tiki Wiki CMS Groupware Project
  3. //
  4. // All Rights Reserved. See copyright.txt for details and a complete list of authors.
  5. // Licensed under the GNU LESSER GENERAL PUBLIC LICENSE. See license.txt for details.
  6. // $Id$
  7. class Search_ContentSource_TrackerItemSource implements Search_ContentSource_Interface, Tiki_Profile_Writer_ReferenceProvider, Search_FacetProvider_Interface
  8. {
  9. private $db;
  10. private $trklib;
  11. private $mode;
  12. private $indexer;
  13. public function __construct($mode = '')
  14. {
  15. $this->db = TikiDb::get();
  16. $this->trklib = TikiLib::lib('trk');
  17. $this->mode = $mode;
  18. }
  19. public function getReferenceMap()
  20. {
  21. return [
  22. 'tracker_id' => 'tracker',
  23. ];
  24. }
  25. public function getDocuments()
  26. {
  27. return $this->db->table('tiki_tracker_items')->fetchColumn('itemId', []);
  28. }
  29. public function getDocument($objectId, Search_Type_Factory_Interface $typeFactory)
  30. {
  31. /*
  32. If you wonder why this method uses straight SQL and not trklib, it's because
  33. trklib performs no meaningful work when extracting the data and strips all
  34. required semantics.
  35. */
  36. $data = [];
  37. $item = $this->trklib->get_tracker_item($objectId);
  38. if (empty($item)) {
  39. return false;
  40. }
  41. $itemObject = Tracker_Item::fromInfo($item);
  42. if (empty($itemObject) || ! $itemObject->getDefinition()) { // ignore corrupted items, e.g. where trackerId == 0
  43. return false;
  44. }
  45. $permNeeded = $itemObject->getViewPermission();
  46. $specialUsers = $itemObject->getSpecialPermissionUsers($objectId, 'View');
  47. $definition = Tracker_Definition::get($item['trackerId']);
  48. if (! $definition) {
  49. return $data;
  50. }
  51. $fieldPermissions = [];
  52. foreach (self::getIndexableHandlers($definition, $item) as $handler) {
  53. if ($this->indexer) {
  54. $this->indexer->errorContext = 'Field ' . $handler->getConfiguration('fieldId') . ' / ' . $handler->getConfiguration('name');
  55. }
  56. $documentPart = $handler->getDocumentPart($typeFactory, $this->mode);
  57. $data = array_merge($data, $documentPart);
  58. $field = $handler->getFieldDefinition();
  59. if ($field['isHidden'] != 'n' || ! empty($field['visibleBy'])) {
  60. $fieldPermissions[$field['permName']] = array_merge(
  61. $itemObject->getAllowedUserGroupsForField($field),
  62. ['perm_names' => array_keys($documentPart)]
  63. );
  64. }
  65. }
  66. if ($this->indexer) {
  67. $this->indexer->errorContext = null;
  68. }
  69. $ownerGroup = $itemObject->getOwnerGroup();
  70. $data = array_merge(
  71. [
  72. 'title' => $typeFactory->sortable($this->trklib->get_isMain_value($item['trackerId'], $objectId)),
  73. 'modification_date' => $typeFactory->timestamp($item['lastModif']),
  74. 'creation_date' => $typeFactory->timestamp($item['created']),
  75. 'contributors' => $typeFactory->multivalue(array_unique([$item['createdBy'], $item['lastModifBy']])),
  76. 'date' => $typeFactory->timestamp($item['created']),
  77. 'tracker_status' => $typeFactory->identifier($item['status']),
  78. 'tracker_id' => $typeFactory->identifier($item['trackerId']),
  79. 'view_permission' => $typeFactory->identifier($permNeeded),
  80. 'parent_object_id' => $typeFactory->identifier($item['trackerId']),
  81. 'parent_object_type' => $typeFactory->identifier('tracker'),
  82. 'field_permissions' => $typeFactory->plaintext(json_encode($fieldPermissions)),
  83. // Fake attributes, removed before indexing
  84. '_extra_users' => $specialUsers,
  85. '_permission_accessor' => $itemObject->getPerms(),
  86. '_extra_groups' => $ownerGroup ? [$ownerGroup] : null,
  87. ],
  88. $data
  89. );
  90. if (empty($data['title'])) {
  91. $data['title'] = $typeFactory->sortable(tr('Unknown'));
  92. }
  93. if (empty($data['language'])) {
  94. $data['language'] = $typeFactory->identifier('unknown');
  95. }
  96. return $data;
  97. }
  98. public function getProvidedFields()
  99. {
  100. static $data;
  101. if (is_array($data)) {
  102. return $data;
  103. }
  104. $data = [
  105. 'title',
  106. 'language',
  107. 'modification_date',
  108. 'creation_date',
  109. 'date',
  110. 'contributors',
  111. 'tracker_status',
  112. 'tracker_id',
  113. 'view_permission',
  114. 'parent_object_id',
  115. 'parent_object_type',
  116. ];
  117. foreach ($this->getAllIndexableHandlers() as $handler) {
  118. $data = array_merge($data, $handler->getProvidedFields());
  119. }
  120. return array_unique($data);
  121. }
  122. public function getGlobalFields()
  123. {
  124. static $data;
  125. if (is_array($data)) {
  126. return $data;
  127. }
  128. $data = [];
  129. foreach ($this->getAllIndexableHandlers() as $handler) {
  130. $data = array_merge($data, $handler->getGlobalFields());
  131. }
  132. $data['title'] = true;
  133. $data['date'] = true;
  134. return $data;
  135. }
  136. public static function getIndexableHandlers($definition, $item = [])
  137. {
  138. return self::getHandlersMatching('Tracker_Field_Indexable', $definition, $item);
  139. }
  140. private static function getHandlersMatching($interface, $definition, $item)
  141. {
  142. global $prefs;
  143. $factory = $definition->getFieldFactory();
  144. $handlers = [];
  145. foreach ($definition->getFields() as $field) {
  146. if ($prefs['unified_trackerfield_keys'] === 'permName' && isset($field['permName']) && strlen($field['permName']) > Tracker_Item::PERM_NAME_MAX_ALLOWED_SIZE) {
  147. continue;
  148. }
  149. if ($prefs['unified_exclude_nonsearchable_fields'] === 'y' && $field['isSearchable'] !== 'y') {
  150. continue;
  151. }
  152. $handler = $factory->getHandler($field, $item);
  153. if ($handler instanceof $interface) {
  154. $handlers[] = $handler;
  155. }
  156. }
  157. return $handlers;
  158. }
  159. private function getAllIndexableHandlers()
  160. {
  161. $trackers = $this->db->table('tiki_trackers')->fetchColumn('trackerId', []);
  162. $handlers = [];
  163. foreach ($trackers as $trackerId) {
  164. $definition = Tracker_Definition::get($trackerId);
  165. $handlers = array_merge($handlers, self::getIndexableHandlers($definition));
  166. }
  167. return $handlers;
  168. }
  169. public function getFacets()
  170. {
  171. global $prefs;
  172. $trackers = $this->db->table('tiki_trackers')->fetchColumn('trackerId', []);
  173. $handlers = [];
  174. foreach ($trackers as $trackerId) {
  175. $definition = Tracker_Definition::get($trackerId);
  176. $handlers = array_merge($handlers, self::getHandlersMatching('Search_FacetProvider_Interface', $definition, []));
  177. }
  178. $source = new Search_FacetProvider();
  179. $source->addFacets([
  180. Search_Query_Facet_Term::fromField('tracker_id')
  181. ->setLabel(tr('Tracker'))
  182. ->setRenderCallback(function ($id) {
  183. $lib = TikiLib::lib('object');
  184. return $lib->get_title('tracker', $id);
  185. }),
  186. Search_Query_Facet_Term::fromField('tracker_status')
  187. ->setLabel(tr('Tracker Status'))
  188. ->setRenderCallback(function ($status) {
  189. $statuses = [
  190. 'o' => 'Open',
  191. 'p' => 'Pending',
  192. 'c' => 'Closed'
  193. ];
  194. return $statuses[$status];
  195. })
  196. ]);
  197. foreach ($handlers as $handler) {
  198. if ($prefs['unified_exclude_nonsearchable_fields_from_facets'] !== 'y' || $handler->getConfiguration('isSearchable') === 'y') {
  199. $source->addProvider($handler);
  200. }
  201. }
  202. return $source->getFacets();
  203. }
  204. public function setIndexer($indexer)
  205. {
  206. $this->indexer = $indexer;
  207. }
  208. }