Source for file indexer.php

Documentation is available at indexer.php

  1. <?php
  2.  
  3. /**
  4. * @package midcom.services
  5. * @author The Midgard Project, http://www.midgard-project.org
  6. * @version $Id: indexer.php,v 1.20.2.3 2005/07/06 13:36:52 torben Exp $
  7. * @copyright The Midgard Project, http://www.midgard-project.org
  8. * @license http://www.gnu.org/licenses/lgpl.html GNU Lesser General Public License
  9. */
  10.  
  11. // First, load dependant classes:
  12. require('indexer/backend.php');
  13. require('indexer/filter.php');
  14. require('indexer/filter_date.php');
  15. require('indexer/document.php');
  16.  
  17. // Load inherited classes
  18. // TODO: Find some more dynamic way for this.
  19.  
  20. require('indexer/document_midcom.php');
  21. require('indexer/document_datamanager.php');
  22. require('indexer/document_attachment.php');
  23.  
  24.  
  25. /**
  26. * This class is the main access point into the MidCOM Indexer subsystem.
  27. *
  28. * It allows you to maintain and query the MidCOM document index.
  29. *
  30. * Do not instantinate this class directly. Instead use the get_service
  31. * method on midcom_application using the service name 'indexer' to obtain
  32. * a running instance. You <i>must</i> honor the reference of that call.
  33. *
  34. *
  35. *
  36. * @package midcom.services
  37. * @see midcom_services_indexer_document
  38. * @see midcom_services_indexer_backend
  39. * @see midcom_services_indexer_filter
  40. *
  41. * @todo Batch indexing support
  42. * @todo Write code examples
  43. * @todo More elaborate class introduction.
  44. */
  45.  
  46. class midcom_services_indexer
  47. {
  48. /**
  49. * The backend indexer implementation
  50. *
  51. * @access private
  52. * @var midcom_services_indexer_backend
  53. */
  54. var $_backend = null;
  55. /**
  56. * Flag for disabled indexing, set by the constructor.
  57. *
  58. * @access private
  59. * @var bool
  60. */
  61. var $_disabled = false;
  62. /**
  63. * Initialization
  64. *
  65. * The constructor will initialize the indexer backend using the MidCOM
  66. * configuration by default. If you need a different indexer backend, you
  67. * can always explicitly instantinate a backend and pass it ot the
  68. * constructor. In that case you have to load the corresponding PHP file
  69. * manually.
  70. *
  71. * @param midcom_services_indexer_backend $backend An explicit indexer to initialize with.
  72. */
  73. function midcom_services_indexer($backend = null)
  74. {
  75. if ($GLOBALS['midcom_config']['indexer_backend'] == false)
  76. {
  77. $this->_disabled = true;
  78. return;
  79. }
  80. if (is_null($backend))
  81. {
  82. require_once("indexer/backend_{$GLOBALS['midcom_config']['indexer_backend']}.php");
  83. $class = "midcom_services_indexer_backend_{$GLOBALS['midcom_config']['indexer_backend']}";
  84. $this->_backend = new $class();
  85. }
  86. else
  87. {
  88. $this->_backend = $backend;
  89. }
  90. }
  91. /**
  92. * Adds a document to the index.
  93. *
  94. * A finished document object must be passed to this object. If the index
  95. * already contains a record with the same Resource Identifier, the record
  96. * is replaced.
  97. *
  98. * Support of batch-indexing using an Array of documents instead of a single
  99. * document is possible (and strongly advised for performance reasons).
  100. *
  101. *
  102. *
  103. * @param mixed $documents One or more documents to be indexed, so this is either a
  104. * midcom_services_indexer_document or an Array of these objects.
  105. * @return bool Indicating success.
  106. */
  107. function index ($documents)
  108. {
  109. if ($this->_disabled)
  110. {
  111. return true;
  112. }
  113. if (! is_array($documents))
  114. {
  115. $documents = Array($documents);
  116. }
  117. if (count($documents) == 0)
  118. {
  119. // Nothing to do.
  120. return true;
  121. }
  122. foreach ($documents as $key => $value)
  123. {
  124. // Process the document, if neccessary, create the corresponding object first.
  125. if (is_a($documents[$key], 'midcom_helper_datamanager'))
  126. {
  127. // Make a copy, as the document is created by-reference and this might make problems during the iterations.
  128. $datamanager = $value;
  129. $datamanager->reindex_autoindex_blobs();
  130. $documents[$key] = $this->new_document($datamanager);
  131. $datamanager->destroy();
  132. }
  133. if (! is_a($documents[$key], 'midcom_services_indexer_document'))
  134. {
  135. debug_push('midcom_services_indexer:index');
  136. debug_add("Encountered an unknown class while processing the document {$key}, aborting. See the debug messages for details.",
  137. MIDCOM_LOG_ERROR);
  138. debug_print_r("The document at type {$key} is invalid:", $document[$key]);
  139. debug_pop();
  140. $GLOBALS['midcom']->generate_error(MIDCOM_ERRCRIT, "Encountered an unknown class while processing the document {$key}");
  141. }
  142. $documents[$key]->members_to_fields();
  143. }
  144. return $this->_backend->index($documents);
  145. }
  146. /**
  147. * Removes the document with the given resource identifier from the index.
  148. *
  149. * @param string $RI The resource identifier of the document that should be deleted.
  150. * @return bool Indicating success.
  151. */
  152. function delete ($RI)
  153. {
  154. if ($this->_disabled)
  155. {
  156. return true;
  157. }
  158. return $this->_backend->delete($RI);
  159. }
  160. /**
  161. * Clear the index completly.
  162. *
  163. * This will drop the current index.
  164. *
  165. * @return bool Indicating success.
  166. */
  167. function delete_all()
  168. {
  169. if ($this->_disabled)
  170. {
  171. return true;
  172. }
  173. return $this->_backend->delete_all();
  174. }
  175. /**
  176. * Query the index and, if set, restrict the query by a given filter.
  177. *
  178. * The filter argument is optional and may be a subclass of indexer_filter.
  179. * The backend determines what filters are supported and how they are
  180. * treated.
  181. *
  182. * The query syntax is also dependant on the backend. Refer to its documentation
  183. * how queries should be built.
  184. *
  185. * Each result node is looked up in NAP/Metadata to verify its visibility.
  186. *
  187. * @param string $query The query, which must suite the backends query syntax. It is assumed to be in the site charset.
  188. * @param midcom_services_indexer_filter $filter An optional filter used to restrict the query.
  189. * @return Array An arary of documents matching the query, or false on a failure.
  190. */
  191. function query ($query, $filter = null)
  192. {
  193. if ($this->_disabled)
  194. {
  195. return false;
  196. }
  197. global $midcom_config;
  198. // Do charset translations
  199. $i18n =& $GLOBALS['midcom']->get_service('i18n');
  200. $query = $i18n->convert_to_utf8($query);
  201. $nav = new midcom_helper_nav();
  202. $result_raw = $this->_backend->query ($query, $filter);
  203. if ($result_raw === false)
  204. {
  205. debug_add("Failed to execute the query, aborting.", MIDCOM_LOG_INFO);
  206. return false;
  207. }
  208. $result = Array();
  209. foreach ($result_raw as $document)
  210. {
  211. $document->fields_to_members();
  212. // Permission checks
  213. debug_add("Doing Permission and Visibility Checks for {$document->title}");
  214. // Topic visibility
  215. $node = null;
  216. $topic = null;
  217. if ($document->topic_guid != '')
  218. {
  219. // Try to get a NAP object to verify visibility and access permissions.
  220. $node = $nav->resolve_guid($document->topic_guid);
  221. if ($node === false)
  222. {
  223. // Skip document, this topic is hidden.
  224. debug_add("Skipping the document {$document->title}, its topic {$document->topic_guid} seems to be invisible");
  225. continue;
  226. }
  227. $topic = $node[MIDCOM_NAV_OBJECT];
  228. }
  229. // For all midcom doucments, check the metadata visibility state given by the source object.
  230. if ($document->is_a('midcom'))
  231. {
  232. $metadata =& midcom_helper_metadata::retrieve($document->source);
  233. if (is_object($metadata))
  234. {
  235. if ( (! $midcom_config['show_hidden_objects'] && ! $metadata->is_visible())
  236. || (! $midcom_config['show_unapproved_objects'] && ! $metadata->is_approved()))
  237. {
  238. debug_add("Skipping the document {$document->title}, the metadata of the source document {$document->source} indicate no visibility.");
  239. debug_add("show_hidden_objects: {$midcom_config['show_hidden_objects']}; got: " . $metadata->is_visible());
  240. debug_add("show_unapproved_objects: {$midcom_config['show_unapproved_objects']}; got: " . $metadata->is_approved());
  241. continue;
  242. }
  243. }
  244. else
  245. {
  246. debug_add("Failed tor retrieve Metadata for {$document->title} using {$document->source}, doing no checks for this object.");
  247. }
  248. // Drop the reference again.
  249. unset($metadata);
  250. }
  251. // Check for additional security checks by the component or a custom callback
  252. $component_loader =& $GLOBALS['midcom']->get_component_loader();
  253. $security = explode(':', $document->security, 2);
  254. switch ($security[0])
  255. {
  256. case 'component':
  257. // Component security, get the interface base class, if it exists, and
  258. // execute the corresponding handler.
  259. debug_add('Doing additional component-level security check');
  260. $interface =& $component_loader->get_interface_class($document->component);
  261. if ( ! is_null($interface)
  262. && ! is_null($node)
  263. && ! $interface->check_document_permissions($document, $topic))
  264. {
  265. debug_add('Skipping the document, the callee returned false.');
  266. continue;
  267. }
  268. break;
  269. case 'function':
  270. // Execute a custom callback to ascertain visbility.
  271. debug_add("We are in function security mode, executing the callback {$security[1]}.");
  272. if (! $security[1]($document, $topic))
  273. {
  274. debug_add('Skipping the document, the callee returned false.');
  275. continue;
  276. }
  277. break;
  278. case 'class':
  279. // Execute a custom callback to ascertain visbility.
  280. debug_add("We are in function security mode, executing the callback {$security[1]}.");
  281. $instance =& $class->get_instance();
  282. if (! $instance->check_document_permissions($document, $topic))
  283. {
  284. debug_add('Skipping the document, the callee returned false.');
  285. continue;
  286. }
  287. break;
  288. }
  289. $result[] = $document;
  290. }
  291. return $result;
  292. }
  293. function _check_permissions_topic($document)
  294. {
  295. }
  296. /**
  297. * This function tries to instantinate the most specific document class
  298. * for the object given in the parameter.
  299. *
  300. * This class will not return empty document base class instances if nothing
  301. * specific can be found. If you are in this situation, you need to instantinate
  302. * an appropriate document manually and populate it.
  303. *
  304. * The checking sequence is like this right now:
  305. *
  306. * 1. If a datamanager instance is passed, it is transformed into a midcom_services_indexer_document_datamanager.
  307. * 2. If a Metadata object is passed, it is transformed into a midcom_services_indexer_document_midcom.
  308. * 3. Finally, the method tries to retrieve a MidCOM Metadata object using the parameter directly. If successful,
  309. * again a midcom_services_indexer_document_midcom is returned.
  310. *
  311. * This factory method will work even if the indexer is disabled. You therefore
  312. * need to protect your code by checking against the configuration option
  313. * indexer_backend !== false.
  314. *
  315. * @param object $object The object for which a document instance is required, passed by reference.
  316. * @return midcom_services_indexer_document A valid document class as specific as possible. Returns
  317. * false on error or if no specific class match could be found.
  318. */
  319. function new_document(&$object)
  320. {
  321. debug_push('midcom_services_indexer::new_document');
  322. debug_print_type('Searching an instance for this object type:', $object);
  323. // Scan for datamanager instances.
  324. if (is_a($object, 'midcom_helper_datamanager'))
  325. {
  326. debug_add('This is a document_datamanager');
  327. debug_pop();
  328. return new midcom_services_indexer_document_datamanager($object);
  329. }
  330. // Maybe we have a metadata object...
  331. if (is_a($object, 'midcom_helper_metadata'))
  332. {
  333. debug_add('This is a metadata document, built from a metadata object.');
  334. debug_pop();
  335. return new midcom_services_indexer_document_midcom($object);
  336. }
  337. // Try to get a metadata object for the argument passed
  338. $metadata =& midcom_helper_metadata::retrieve($object);
  339. if ($metadata !== false)
  340. {
  341. debug_add('Successfully fetched a Metadata object for the argument.');
  342. debug_pop();
  343. return new midcom_services_indexer_document_midcom($metadata);
  344. }
  345. // No specific match found.
  346. debug_add('No match found for this type.');
  347. debug_pop();
  348. return false;
  349. }
  350. }
  351.  
  352. ?>

Documentation generated on Mon, 21 Nov 2005 18:16:24 +0100 by phpDocumentor 1.3.0RC3